usb: getting string descriptors, minor improvements
[quarnos.git] / resources / usb.cpp
blob36111330fc5d2ac44ffaa5600a455c13803cf24d
1 /* Quarn OS
3 * USB bus
5 * Copyright (C) 2009 Pawel Dziepak
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "pci.h"
24 #include "usb.h"
25 #include "uhci.h"
27 #include "manes/manec.h"
29 using namespace resources;
31 int usb_count = 0;
33 bool usb::init_bus(p<device> dev) {
34 host = dev.cast<usb_hc>();
36 if (!host.valid())
37 return false;
39 host->scan_bus(delegate<void, int>::method(this, &usb::device_connected));
41 return true;
44 int usb::get_count() {
45 return 2;
48 #define SET_ADDRESS 5
49 #define GET_DESCRIPTOR 6
50 #define GET_CONFIGURATION 8
51 #define SET_CONFIGURATION 9
53 string usb::get_dev_string(int index, int addr) {
54 if (!index)
55 return string();
57 usb_setup_data setup;
58 setup.bmRequestType = 0x80;
59 setup.bRequest = GET_DESCRIPTOR;
60 setup.wValue = 3 << 8 | index;
61 setup.wIndex = 0;
62 setup.wLength = 1;
63 int size = *(char*)host->control_transfer(pid_setup, &setup, sizeof(usb_setup_data), 1, addr);
65 setup.wLength = size;
66 char *bytes = (char*)host->control_transfer(pid_setup, &setup, sizeof(usb_setup_data), size, addr);
67 bytes += 2;
69 return string::from_utf16(bytes);
72 void usb::device_connected(int port) {
73 usb_count++;
75 /* Get device descriptor */
76 usb_setup_data setup;
77 setup.bmRequestType = 0x80;
78 setup.bRequest = GET_DESCRIPTOR;
79 setup.wValue = 1 << 8;
80 setup.wIndex = 0;
81 setup.wLength = 16;
83 device_descriptor *dev = (device_descriptor*)host->control_transfer(pid_setup, &setup, sizeof(usb_setup_data), sizeof(device_descriptor),0);
85 u8 addr = host->get_free_address();
87 /* Set device address */
88 setup.bmRequestType = 0;
89 setup.bRequest = SET_ADDRESS;
90 setup.wValue = addr;
91 setup.wIndex = 0;
92 setup.wLength = 0;
94 host->control_transfer(pid_setup, &setup, sizeof(usb_setup_data), 0,0);
96 /* Get device descriptor */
97 setup.bmRequestType = 0x80;
98 setup.bRequest = GET_DESCRIPTOR;
99 setup.wValue = 1 << 8;
100 setup.wIndex = 0;
101 setup.wLength = 16;
103 dev = (device_descriptor*)host->control_transfer(pid_setup, &setup, sizeof(usb_setup_data), sizeof(device_descriptor),addr);
104 get_dev_string(dev->iProduct, addr);
106 /* Get configuration descriptor */
107 setup.bmRequestType = 0x80;
108 setup.bRequest = GET_DESCRIPTOR;
109 setup.wValue = 2 << 8;
110 setup.wIndex = 0;
111 setup.wLength = 0x20;
112 configuration_descriptor *conf = (configuration_descriptor*)host->control_transfer(pid_setup, &setup, sizeof(usb_setup_data), 0x20/* sizeof(configuration_descriptor)*/, addr);
114 p<usb_did> id = new usb_did(this, addr, (interface_descriptor*)((unsigned int)conf + conf->bLength));
115 endpoint_descriptor *endp = (endpoint_descriptor*)((unsigned int)conf + conf->bLength + 9);
117 int read_ep = 0;
118 int write_ep = 0;
119 int control_ep = 0;
121 while (endp->bDescriptorType == 5) {
122 if (endp->bmAttributes != 2)
123 continue;
125 if (endp->bEndpointAddress & 0x80)
126 read_ep = endp->bEndpointAddress & ~0x80;
127 else
128 write_ep = endp->bEndpointAddress;
130 endp = endp + 1;
133 id->set_endps(control_ep, read_ep, write_ep);
134 id->set_conf(conf->bConfigurationValue);
135 create_device(id);
136 __asm__ __volatile__("cli\nhlt"::"a"(conf),"b"(write_ep),"c"(read_ep));
140 void usb::set_conf(int addr, int conf) {
141 usb_setup_data setup;
142 setup.bmRequestType = 0;
143 setup.bRequest = SET_CONFIGURATION;
144 setup.wValue = conf;
145 setup.wIndex = 0;
146 setup.wLength = 0;
148 host->control_transfer(pid_setup, &setup, sizeof(usb_setup_data), 0, addr);
151 void usb::register_type() {
152 manes::manec::get()->register_type<usb>("usb", "pci");