scsi request, part usb mass storage class driver, bulk transfers
[quarnos.git] / resources / usb.cpp
blob9824847694aa62def6f516ce0b9289e45cd9b88a
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 void usb::device_connected(int port) {
54 usb_count++;
56 /* Get device descriptor */
57 usb_setup_data setup;
58 setup.bmRequestType = 0x80;
59 setup.bRequest = GET_DESCRIPTOR;
60 setup.wValue = 1 << 8;
61 setup.wIndex = 0;
62 setup.wLength = 16;
64 device_descriptor *dev = (device_descriptor*)host->control_transfer(pid_setup, &setup, sizeof(usb_setup_data), sizeof(device_descriptor),0);
66 u8 addr = host->get_free_address();
68 /* Set device address */
69 setup.bmRequestType = 0;
70 setup.bRequest = SET_ADDRESS;
71 setup.wValue = addr;
72 setup.wIndex = 0;
73 setup.wLength = 0;
75 host->control_transfer(pid_setup, &setup, sizeof(usb_setup_data), 0,0);
77 /* Get device descriptor */
78 setup.bmRequestType = 0x80;
79 setup.bRequest = GET_DESCRIPTOR;
80 setup.wValue = 1 << 8;
81 setup.wIndex = 0;
82 setup.wLength = 16;
84 dev = (device_descriptor*)host->control_transfer(pid_setup, &setup, sizeof(usb_setup_data), sizeof(device_descriptor),addr);
86 /* Get configuration descriptor */
87 setup.bmRequestType = 0x80;
88 setup.bRequest = GET_DESCRIPTOR;
89 setup.wValue = 2 << 8;
90 setup.wIndex = 0;
91 setup.wLength = 0x20;
92 configuration_descriptor *conf = (configuration_descriptor*)host->control_transfer(pid_setup, &setup, sizeof(usb_setup_data), 0x20/* sizeof(configuration_descriptor)*/, addr);
94 p<usb_did> id = new usb_did(this, addr, (interface_descriptor*)((unsigned int)conf + conf->bLength));
95 endpoint_descriptor *endp = (endpoint_descriptor*)((unsigned int)conf + conf->bLength + 9);
97 int read_ep = 0;
98 int write_ep = 0;
99 int control_ep = 0;
101 while (endp->bDescriptorType == 5) {
102 if (endp->bmAttributes != 2)
103 continue;
105 if (endp->bEndpointAddress & 0x80)
106 read_ep = endp->bEndpointAddress & ~0x80;
107 else
108 write_ep = endp->bEndpointAddress;
110 endp = endp + 1;
113 id->set_endps(control_ep, read_ep, write_ep);
114 create_device(id);
115 __asm__ __volatile__("cli\nhlt"::"a"(conf),"b"(write_ep),"c"(read_ep));
119 void usb::set_conf(int addr) {
120 usb_setup_data setup;
121 setup.bmRequestType = 0;
122 setup.bRequest = SET_CONFIGURATION;
123 setup.wValue = 1;
124 setup.wIndex = 0;
125 setup.wLength = 0;
127 host->control_transfer(pid_setup, &setup, sizeof(usb_setup_data), 0, addr);
130 void usb::register_type() {
131 manes::manec::get()->register_type<usb>("usb", "pci");