xref: /haiku/src/add-ons/kernel/bus_managers/usb/Device.cpp (revision 5412911f7f8ca41340b0f5cb928ed9726322ab44)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2003-2004, Niels S. Reedijk
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 
22 #include "usb_p.h"
23 
24 Device::Device( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum , bool lowspeed )
25 {
26 	status_t retval;
27 
28 	m_bus = bus;
29 	m_parent = parent;
30 	m_initok = false;
31 	m_configurations = 0;
32 	m_current_configuration = 0;
33 
34 	dprintf( "USB Device: new device\n" );
35 
36 	//1. Create the semaphore
37 	m_lock = create_sem( 1 , "device_sem" );
38 	if ( m_lock < B_OK )
39 	{
40 		dprintf( "usb Device: could not create semaphore\n" );
41 		return;
42 	}
43 	set_sem_owner( m_lock , B_SYSTEM_TEAM );
44 
45 	//2. Set the free entry free entry in the device map (for the device number)
46 	m_devicenum = devicenum;
47 
48 	//3. Set up the pipe stuff
49 	//Set the maximum transfer numbers for the incoming and the outgoing packets on endpoint 0
50 	m_maxpacketin[0] = m_maxpacketout[0] = m_device_descriptor.max_packet_size_0;
51 	m_device_descriptor = desc;
52 	m_lowspeed = lowspeed;
53 	m_defaultPipe = new ControlPipe( this , Pipe::Default , 0 );
54 
55 	//4. Get the device descriptor
56 	// We already have a part of it, but we want it all
57 	retval = GetDescriptor( USB_DESCRIPTOR_DEVICE , 0 ,
58 	                        (void *)&m_device_descriptor , sizeof(m_device_descriptor ) );
59 
60 	if ( retval != sizeof( m_device_descriptor ) )
61 	{
62 		dprintf( "usb Device: error while getting the device descriptor\n" );
63 		return;
64 	}
65 
66 	dprintf( "usb Device %d: Vendor id: %d , Product id: %d\n" , devicenum ,
67 	         m_device_descriptor.vendor_id , m_device_descriptor.product_id );
68 
69 	// 4. Get the configurations
70 	m_configurations = (usb_configuration_descriptor *)malloc( m_device_descriptor.num_configurations * sizeof (usb_configuration_descriptor) );
71 	if ( m_configurations == 0 )
72 	{
73 		dprintf( "usb Device: out of memory during config creations!\n" );
74 		return;
75 	}
76 
77 	for ( int i = 0 ; i < m_device_descriptor.num_configurations ; i++ )
78 	{
79 		if ( GetDescriptor( USB_DESCRIPTOR_CONFIGURATION , i ,
80 		     (void *)( m_configurations + i ) , sizeof (usb_configuration_descriptor ) ) != sizeof( usb_configuration_descriptor ) )
81 		{
82 			dprintf( "usb Device %d: error fetching configuration %d ...\n" , m_devicenum , i );
83 			return;
84 		}
85 	}
86 
87 	// 5. Set the default configuration
88 	dprintf( "usb Device %d: setting configuration %d\n" , m_devicenum , 0 );
89 	SetConfiguration( 0 );
90 
91 	//6. TODO: Find drivers for the device
92 
93 	m_initok = true;
94 }
95 
96 //Returns the length that was copied (index gives the number of the config)
97 int16 Device::GetDescriptor( uint8 descriptor_type , uint16 index ,
98                                 void *buffer , size_t size )
99 {
100 	size_t actual_length = 0;
101 	m_defaultPipe->SendRequest(USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD , //Type
102 	             USB_REQUEST_GET_DESCRIPTOR ,					//Request
103 	             ( descriptor_type << 8 ) | index ,				//Value
104 	             0 ,											//Index
105 	             size ,											//Length
106 	             buffer ,										//Buffer
107 	             size ,											//Bufferlength
108 	             &actual_length );								//length
109 	return actual_length;
110 }
111 
112 status_t Device::SetConfiguration( uint8 value )
113 {
114 	if ( value >= m_device_descriptor.num_configurations )
115 		return EINVAL;
116 
117 	m_defaultPipe->SendRequest( USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD , //Type
118 	             USB_REQUEST_SET_CONFIGURATION ,				//Request
119 	             value ,										//Value
120 	             0 ,											//Index
121 	             0 ,											//Length
122 	             NULL ,											//Buffer
123 	             0 ,											//Bufferlength
124 	             0 );											//length
125 
126 	//Set current configuration
127 	m_current_configuration = m_configurations + value;
128 	return B_OK;
129 }
130