xref: /haiku/src/add-ons/kernel/bus_managers/usb/Device.cpp (revision 67bce78b48ed6d01b5a8eef89f5694c372b7e0a1)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2003, 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 )
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. Get the device descriptor
49 	// We already have a part of it, but we want it all
50 	m_device_descriptor = desc;
51 
52 	//Set the maximum transfer numbers for the incoming and the outgoing packets on endpoint 0
53 	m_maxpacketin[0] = m_maxpacketout[0] = m_device_descriptor.max_packet_size_0;
54 
55 	retval = GetDescriptor( USB_DESCRIPTOR_DEVICE , 0 ,
56 	                        (void *)&m_device_descriptor , sizeof(m_device_descriptor ) );
57 
58 	if ( retval != sizeof( m_device_descriptor ) )
59 	{
60 		dprintf( "usb Device: error while getting the device descriptor\n" );
61 		return;
62 	}
63 
64 	dprintf( "usb Device %d: Vendor id: %d , Product id: %d\n" , devicenum ,
65 	         m_device_descriptor.vendor_id , m_device_descriptor.product_id );
66 
67 
68 	// 4. Get the configurations
69 	m_configurations = (usb_configuration_descriptor *)malloc( m_device_descriptor.num_configurations * sizeof (usb_configuration_descriptor) );
70 	if ( m_configurations == 0 )
71 	{
72 		dprintf( "usb Device: out of memory during config creations!\n" );
73 		return;
74 	}
75 
76 	for ( int i = 0 ; i < m_device_descriptor.num_configurations ; i++ )
77 	{
78 		if ( GetDescriptor( USB_DESCRIPTOR_CONFIGURATION , i ,
79 		     (void *)( m_configurations + i ) , sizeof (usb_configuration_descriptor ) ) != sizeof( usb_configuration_descriptor ) )
80 		{
81 			dprintf( "usb Device %d: error fetching configuration %d ...\n" , m_devicenum , i );
82 			return;
83 		}
84 	}
85 
86 	// 5. Set the default configuration
87 	dprintf( "usb Device %d: setting configuration %d\n" , m_devicenum , 0 );
88 	SetConfiguration( 0 );
89 
90 	//6. TODO: Find drivers for the device
91 }
92 
93 //Returns the length that was copied (index gives the number of the config)
94 int16 Device::GetDescriptor( uint8 descriptor_type , uint16 index ,
95                                 void *buffer , size_t size )
96 {
97 	size_t actual_length;
98 	m_bus->SendRequest( this ,
99 	             USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD , //Type
100 	             USB_REQUEST_GET_DESCRIPTOR ,					//Request
101 	             ( descriptor_type << 8 ) | index ,				//Value
102 	             0 ,											//Index
103 	             size ,											//Length
104 	             buffer ,										//Buffer
105 	             size ,											//Bufferlength
106 	             &actual_length );								//length
107 	return actual_length;
108 }
109 
110 status_t Device::SetConfiguration( uint8 value )
111 {
112 	if ( value >= m_device_descriptor.num_configurations )
113 		return EINVAL;
114 
115 	m_bus->SendRequest( this ,
116 	             USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD , //Type
117 	             USB_REQUEST_SET_CONFIGURATION ,				//Request
118 	             value ,										//Value
119 	             0 ,											//Index
120 	             0 ,											//Length
121 	             NULL ,											//Buffer
122 	             0 ,											//Bufferlength
123 	             0 );											//length
124 
125 	//Set current configuration
126 	m_current_configuration = m_configurations + value;
127 }
128