Forum: Mikrocontroller und Digitale Elektronik USB-Kombigerät: zwischen HID und MSC umschalten


von Peter Parker (Gast)


Lesenswert?

Hallo zusammen!
Ich möchte hier ein USB-Gerät bauen, das einerseits als HID 
kommuniziert, andererseits sein Flash als Massenspeicher exportiert. Was 
ich bisher erreicht habe:
-HID läuft
-MSC läuft
-HID und MSC laufen gleichzeitig
Aber ich möchte zumindest das MSC abschalten können, am besten vom Gerät 
aus (also nicht mit einem USB-Befehl, der vom PC kommt). Also eine 
Option wäre, das HID läuft immer und ich schalte das MSC dazu oder weg. 
Oder ich wechsel komplett, so dass das HID weg ist, wenn das Gerät als 
MSC läuft.
1. Wie stell ich das an? Vom Verständnis des USB-Protokolls her kann ich 
entweder HID und MSC als verschiedene Konfigurationen definieren oder 
als verschiedene alternate interfaces. Verschiedene Konfigurationen 
macht man anscheinend nicht. Was sind denn die Vor- und Nachteile der 
jeweiligen Lösungen?
2. Außerdem frage ich mich: muss ich mich selber darum kümmern, dass der 
PC eine Variante auswählt? Denn mein Client-Programm (das legendäre 
HIDClient.exe) hängt sich bisher immer auf, wenn ich zwei 
Konfigurationen oder zwei alternate interfaces probiere.
Das sind die Deskriptoren, die ich verwende:
- Für zwei Konfigurationen:
1
const U8 USB_ConfigDescriptor[] = {
2
/* Configuration 1 */
3
  USB_CONFIGUARTION_DESC_SIZE,       /* bLength */
4
  USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
5
  WBVAL(                             /* wTotalLength */
6
    1*USB_CONFIGUARTION_DESC_SIZE +
7
    2*USB_INTERFACE_DESC_SIZE     +
8
      HID_DESC_SIZE               +
9
  4*USB_ENDPOINT_DESC_SIZE
10
  ),
11
  0x01,                              /* bNumInterfaces */
12
  0x01,                              /* bConfigurationValue: 0x01 is used to select this configuration */
13
  0x04,                              /* iConfiguration */
14
  USB_CONFIG_BUS_POWERED,            /* bmAttributes */
15
  USB_CONFIG_POWER_MA(100),          /* bMaxPower, device power consumption is 100 mA */
16
17
/* Interface 0, Alternate Setting 0, HID Class */
18
  USB_INTERFACE_DESC_SIZE,           /* bLength */
19
  USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
20
  0x00,                              /* bInterfaceNumber */
21
  0x00,                              /* bAlternateSetting */
22
  0x02,                              /* bNumEndpoints */
23
  USB_DEVICE_CLASS_HUMAN_INTERFACE,  /* bInterfaceClass */
24
  HID_SUBCLASS_NONE,                 /* bInterfaceSubClass */
25
  HID_PROTOCOL_NONE,                 /* bInterfaceProtocol */
26
  0x05,                              /* iInterface */
27
28
/* HID Class Descriptor */
29
/* HID_DESC_OFFSET = 0x0012 */
30
  HID_DESC_SIZE,                     /* bLength */
31
  HID_HID_DESCRIPTOR_TYPE,           /* bDescriptorType */
32
  WBVAL(0x0100), /* 1.00 */          /* bcdHID */
33
  0x00,                              /* bCountryCode */
34
  0x01,                              /* bNumDescriptors */
35
  HID_REPORT_DESCRIPTOR_TYPE,        /* bDescriptorType */
36
  WBVAL(HID_REPORT_DESC_SIZE),       /* wDescriptorLength */
37
  
38
/* Endpoint, EP1 Interrupt IN */
39
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
40
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
41
  USB_ENDPOINT_IN(1),                /* bEndpointAddress */
42
  USB_ENDPOINT_TYPE_INTERRUPT,       /* bmAttributes */
43
  WBVAL(0x0040),                     /* wMaxPacketSize */
44
  0x20,          /* 32ms */          /* bInterval */
45
46
/* Endpoint, EP1 Interrupt OUT */
47
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
48
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
49
  USB_ENDPOINT_OUT(1),               /* bEndpointAddress */
50
  USB_ENDPOINT_TYPE_INTERRUPT,       /* bmAttributes */
51
  WBVAL(0x0040),                     /* wMaxPacketSize */
52
  0x20,          /* 32ms */          /* bInterval */
53
/* Configuration 2 */
54
  USB_CONFIGUARTION_DESC_SIZE,       /* bLength */
55
  USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
56
  WBVAL(                             /* wTotalLength */
57
    1*USB_CONFIGUARTION_DESC_SIZE +
58
    2*USB_INTERFACE_DESC_SIZE     +
59
  4*USB_ENDPOINT_DESC_SIZE
60
  ),
61
  0x01,                              /* bNumInterfaces */
62
  0x02,                              /* bConfigurationValue: 0x02 is used to select this configuration */
63
  0x04,                              /* iConfiguration */
64
  USB_CONFIG_BUS_POWERED,            /* bmAttributes */
65
  USB_CONFIG_POWER_MA(100),          /* bMaxPower, device power consumption is 100 mA */  
66
/* Interface 0, Alternate Setting 1, MSC Class */
67
  USB_INTERFACE_DESC_SIZE,           /* bLength */
68
  USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
69
  0x00,                              /* bInterfaceNumber */
70
  0x01,                              /* bAlternateSetting */
71
  0x02,                              /* bNumEndpoints */
72
  USB_DEVICE_CLASS_STORAGE,          /* bInterfaceClass */
73
  MSC_SUBCLASS_SCSI,                 /* bInterfaceSubClass */
74
  MSC_PROTOCOL_BULK_ONLY,            /* bInterfaceProtocol */
75
  0x07,                              /* iInterface */
76
77
/* Endpoint, EP2 Bulk IN */
78
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
79
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
80
  USB_ENDPOINT_IN(2),                /* bEndpointAddress */
81
  USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
82
  WBVAL(0x0040),                     /* wMaxPacketSize */
83
  0x00,                              /* bInterval: ignore for Bulk transfer */
84
85
/* Endpoint, EP2 Bulk OUT */
86
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
87
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
88
  USB_ENDPOINT_OUT(2),               /* bEndpointAddress */
89
  USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
90
  WBVAL(0x0040),                     /* wMaxPacketSize */
91
  0x00,                              /* bInterval: ignore for Bulk transfer */
92
  
93
/* Terminator */
94
  0                                  /* bLength */
95
};


- Für zwei alternate interfaces:
1
const U8 USB_ConfigDescriptor[] = {
2
/* Configuration 1 */
3
  USB_CONFIGUARTION_DESC_SIZE,       /* bLength */
4
  USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
5
  WBVAL(                             /* wTotalLength */
6
    1*USB_CONFIGUARTION_DESC_SIZE +
7
    2*USB_INTERFACE_DESC_SIZE     +
8
      HID_DESC_SIZE               +
9
  4*USB_ENDPOINT_DESC_SIZE
10
  ),
11
  0x01,                              /* bNumInterfaces */
12
  0x01,                              /* bConfigurationValue: 0x01 is used to select this configuration */
13
  0x04,                              /* iConfiguration */
14
  USB_CONFIG_BUS_POWERED /*|*/       /* bmAttributes */
15
/*USB_CONFIG_REMOTE_WAKEUP*/,
16
  USB_CONFIG_POWER_MA(100),          /* bMaxPower, device power consumption is 100 mA */
17
18
/* Interface 0, Alternate Setting 0, HID Class */
19
  USB_INTERFACE_DESC_SIZE,           /* bLength */
20
  USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
21
  0x00,                              /* bInterfaceNumber */
22
  0x00,                              /* bAlternateSetting */
23
  0x02,                              /* bNumEndpoints */
24
  USB_DEVICE_CLASS_HUMAN_INTERFACE,  /* bInterfaceClass */
25
  HID_SUBCLASS_NONE,                 /* bInterfaceSubClass */
26
  HID_PROTOCOL_NONE,                 /* bInterfaceProtocol */
27
  0x05,                              /* iInterface */
28
29
/* HID Class Descriptor */
30
/* HID_DESC_OFFSET = 0x0012 */
31
  HID_DESC_SIZE,                     /* bLength */
32
  HID_HID_DESCRIPTOR_TYPE,           /* bDescriptorType */
33
  WBVAL(0x0100), /* 1.00 */          /* bcdHID */
34
  0x00,                              /* bCountryCode */
35
  0x01,                              /* bNumDescriptors */
36
  HID_REPORT_DESCRIPTOR_TYPE,        /* bDescriptorType */
37
  WBVAL(HID_REPORT_DESC_SIZE),       /* wDescriptorLength */
38
  
39
/* Endpoint, EP1 Interrupt IN */
40
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
41
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
42
  USB_ENDPOINT_IN(1),                /* bEndpointAddress */
43
  USB_ENDPOINT_TYPE_INTERRUPT,       /* bmAttributes */
44
  WBVAL(0x0040),                     /* wMaxPacketSize */
45
  0x20,          /* 32ms */          /* bInterval */
46
47
/* Endpoint, EP1 Interrupt OUT */
48
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
49
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
50
  USB_ENDPOINT_OUT(1),               /* bEndpointAddress */
51
  USB_ENDPOINT_TYPE_INTERRUPT,       /* bmAttributes */
52
  WBVAL(0x0040),                     /* wMaxPacketSize */
53
  0x20,          /* 32ms */          /* bInterval */
54
  
55
/* Interface 0, Alternate Setting 1, MSC Class */
56
  USB_INTERFACE_DESC_SIZE,           /* bLength */
57
  USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
58
  0x00,                              /* bInterfaceNumber */
59
  0x01,                              /* bAlternateSetting */
60
  0x02,                              /* bNumEndpoints */
61
  USB_DEVICE_CLASS_STORAGE,          /* bInterfaceClass */
62
  MSC_SUBCLASS_SCSI,                 /* bInterfaceSubClass */
63
  MSC_PROTOCOL_BULK_ONLY,            /* bInterfaceProtocol */
64
  0x07,                              /* iInterface */
65
66
/* Endpoint, EP2 Bulk IN */
67
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
68
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
69
  USB_ENDPOINT_IN(2),                /* bEndpointAddress */
70
  USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
71
  WBVAL(0x0040),                     /* wMaxPacketSize */
72
  0x00,                              /* bInterval: ignore for Bulk transfer */
73
74
/* Endpoint, EP2 Bulk OUT */
75
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
76
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
77
  USB_ENDPOINT_OUT(2),               /* bEndpointAddress */
78
  USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
79
  WBVAL(0x0040),                     /* wMaxPacketSize */
80
  0x00,                              /* bInterval: ignore for Bulk transfer */
81
  
82
/* Terminator */
83
  0                                  /* bLength */
84
};
Hat jemand eine Idee, in welche Richtung ich suchen muss?

Schöne Grüße,
Peter

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Lass doch das MSD die ganze Zeit aktiv, aber sieh Dir an, was z.B. 
Kartenleser machen, wenn aus ihnen die Karte entfernt wird. Das 
MSD-Protokoll dürfte für diesen Fall eine Signalisierung vorsehen -- und 
genau diese solltest Du verwenden können.

von Peter Parker (Gast)


Lesenswert?

Hm, lustige Idee. Aber dann legt doch Windows trotzdem einen 
Laufwerksbuchstaben an, nicht? Zumindest hab ich bei meinem Kartenleser 
immer vier Buchstaben, selbst wenn nur eine Karte steckt.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Peter Parker schrieb:
> Aber dann legt doch Windows trotzdem einen
> Laufwerksbuchstaben an, nicht?

Deswegen kann man bei neueren Windows-Versionen konfigurieren, daß 
"leere Laufwerke" nicht angezeigt werden.

von Peter Parker (Gast)


Lesenswert?

Ah, das wusste ich nicht. Hilft mir aber leider auch nicht weiter, weil 
auch digitale Analphabeten das Ding benutzen sollen. Ich hab 
mittlerweile mit USBlyzer etwas rausbekommen:
Wenn ich nur das HID konfiguriert habe, bekomme ich auf dem Bus 
regelmäßig (alle 32ms, klar) einen "URB Bulk or Interrupt Transfer 
issued" und 64ms später den dazugehörigen (woher weiß der Bus 
eigentlich, welche Antwort zu welcher Anfrage gehört?) "URB Bulk or 
Interrupt Transfer succeeded" mit den Daten, die mein Gerät liefert. 
Aber wenn ich HID und MSC konfiguriere (als alternate settings desselben 
interfaces), sehe ich gar nichts auf dem Bus. Was kann ich denn daraus 
lernen? Nachdem die Enumeratin problemlos läuft, hätte ich erwartet, 
dass der PC schon weiß, wo er die Anfrage hinschicken soll. Aber 
anscheinend ist dem nicht so...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.