xref: /minix3/minix/lib/libddekit/src/usb_client.c (revision 2d64210c1dbcd340904718f2d4e9e81adeab3c7d)
1433d6423SLionel Sambuc #include "common.h"
2433d6423SLionel Sambuc #include <ddekit/usb.h>
3433d6423SLionel Sambuc #include <ddekit/memory.h>
4433d6423SLionel Sambuc #include <ddekit/minix/msg_queue.h>
5433d6423SLionel Sambuc #include <minix/usb.h>
6433d6423SLionel Sambuc 
7433d6423SLionel Sambuc struct ddekit_usb_dev {
8433d6423SLionel Sambuc 	int id;
9433d6423SLionel Sambuc 	unsigned int interfaces;
10433d6423SLionel Sambuc 	void *data;
11433d6423SLionel Sambuc 	struct ddekit_usb_dev *next;
12433d6423SLionel Sambuc 	struct ddekit_usb_dev *prev;
13433d6423SLionel Sambuc };
14433d6423SLionel Sambuc 
15433d6423SLionel Sambuc struct ddekit_usb_dev dev_list_head = {
16433d6423SLionel Sambuc 	.next = &dev_list_head,
17433d6423SLionel Sambuc 	.prev = &dev_list_head,
18433d6423SLionel Sambuc };
19433d6423SLionel Sambuc 
20433d6423SLionel Sambuc static struct ddekit_usb_driver *d_usb_driver;
21433d6423SLionel Sambuc 
22433d6423SLionel Sambuc static void _ddekit_usb_completion(struct usb_urb *mx);
23433d6423SLionel Sambuc static void _ddekit_usb_connect( unsigned int dev_id, unsigned int
24433d6423SLionel Sambuc 	interfaces);
25433d6423SLionel Sambuc static void _ddekit_usb_disconnect(unsigned dev_id);
26433d6423SLionel Sambuc 
27433d6423SLionel Sambuc struct usb_driver mx_usb_driver = {
28433d6423SLionel Sambuc 	.urb_completion = _ddekit_usb_completion,
29433d6423SLionel Sambuc 	.connect_device = _ddekit_usb_connect,
30433d6423SLionel Sambuc 	.disconnect_device = _ddekit_usb_disconnect
31433d6423SLionel Sambuc };
32433d6423SLionel Sambuc 
33433d6423SLionel Sambuc /*****************************************************************************
34433d6423SLionel Sambuc  *         _ddekit_usb_completion                                            *
35433d6423SLionel Sambuc  ****************************************************************************/
_ddekit_usb_completion(struct usb_urb * mx_urb)36433d6423SLionel Sambuc static void _ddekit_usb_completion(struct usb_urb *mx_urb)
37433d6423SLionel Sambuc {
38433d6423SLionel Sambuc 
39433d6423SLionel Sambuc 	struct ddekit_usb_urb *d_urb = (struct ddekit_usb_urb *) mx_urb->priv;
40433d6423SLionel Sambuc 
41433d6423SLionel Sambuc 	/* XXX: copy stuff back into d_urb */
42433d6423SLionel Sambuc 
43433d6423SLionel Sambuc 	d_urb->status         = mx_urb->status;
44433d6423SLionel Sambuc 	d_urb->error_count    = mx_urb->interval;
45433d6423SLionel Sambuc 	d_urb->transfer_flags = mx_urb->error_count;
46433d6423SLionel Sambuc 	d_urb->actual_length  = mx_urb->actual_length;
47433d6423SLionel Sambuc 	d_urb->ddekit_priv    = NULL;
48433d6423SLionel Sambuc 
49433d6423SLionel Sambuc 	if (mx_urb->type == USB_TRANSFER_CTL) {
50433d6423SLionel Sambuc 		memcpy(d_urb->setup_packet, mx_urb->setup_packet, 8);
51433d6423SLionel Sambuc 	}
52433d6423SLionel Sambuc 
53433d6423SLionel Sambuc 	if (mx_urb->type == USB_TRANSFER_ISO) {
54433d6423SLionel Sambuc 		d_urb->start_frame = mx_urb->start_frame;
55433d6423SLionel Sambuc 
56433d6423SLionel Sambuc 		memcpy(d_urb->iso_desc, mx_urb->buffer + d_urb->size,
57433d6423SLionel Sambuc 		       d_urb->number_of_packets * sizeof(struct usb_iso_packet_desc));
58433d6423SLionel Sambuc 	}
59433d6423SLionel Sambuc 
60433d6423SLionel Sambuc 	memcpy(d_urb->data, mx_urb->buffer, d_urb->size);
61433d6423SLionel Sambuc 
62433d6423SLionel Sambuc 	/* free mx_urb */
63433d6423SLionel Sambuc 	ddekit_simple_free(mx_urb);
64433d6423SLionel Sambuc 
65433d6423SLionel Sambuc 	/* 'give back' URB */
66433d6423SLionel Sambuc 
67433d6423SLionel Sambuc 	d_usb_driver->completion(d_urb->priv);
68433d6423SLionel Sambuc }
69433d6423SLionel Sambuc 
70433d6423SLionel Sambuc 
71433d6423SLionel Sambuc /*****************************************************************************
72433d6423SLionel Sambuc  *         _ddekit_usb_connect                                               *
73433d6423SLionel Sambuc  ****************************************************************************/
_ddekit_usb_connect(unsigned int dev_id,unsigned int interfaces)74433d6423SLionel Sambuc static void _ddekit_usb_connect(unsigned int dev_id, unsigned int interfaces)
75433d6423SLionel Sambuc {
76433d6423SLionel Sambuc 	struct ddekit_usb_dev *d_dev = (struct ddekit_usb_dev *)
77433d6423SLionel Sambuc 		ddekit_simple_malloc(sizeof(struct ddekit_usb_dev));
78433d6423SLionel Sambuc 
79433d6423SLionel Sambuc 	d_dev->data       = NULL;
80433d6423SLionel Sambuc 	d_dev->id         = dev_id;
81433d6423SLionel Sambuc 	d_dev->interfaces = interfaces;
82433d6423SLionel Sambuc 
83433d6423SLionel Sambuc 	/* add to list */
84433d6423SLionel Sambuc 
85433d6423SLionel Sambuc 	d_dev->next = dev_list_head.next;
86433d6423SLionel Sambuc 	d_dev->prev = &dev_list_head;
87433d6423SLionel Sambuc 
88433d6423SLionel Sambuc 	dev_list_head.next = d_dev;
89433d6423SLionel Sambuc 	d_dev->next->prev = d_dev;
90433d6423SLionel Sambuc 	d_usb_driver->connect(d_dev, interfaces);
91433d6423SLionel Sambuc }
92433d6423SLionel Sambuc 
93433d6423SLionel Sambuc /*****************************************************************************
94433d6423SLionel Sambuc  *         _ddekit_usb_disconnect                                            *
95433d6423SLionel Sambuc  ****************************************************************************/
_ddekit_usb_disconnect(unsigned dev_id)96433d6423SLionel Sambuc void _ddekit_usb_disconnect(unsigned dev_id)
97433d6423SLionel Sambuc {
98433d6423SLionel Sambuc 	/* find dev */
99433d6423SLionel Sambuc 	struct ddekit_usb_dev *it;
100433d6423SLionel Sambuc 	struct ddekit_usb_dev *d_dev = NULL;
101433d6423SLionel Sambuc 
102433d6423SLionel Sambuc 
103433d6423SLionel Sambuc 	for (it = dev_list_head.next; it != &dev_list_head; it= it->next) {
104433d6423SLionel Sambuc 		if (it->id == dev_id) {
105433d6423SLionel Sambuc 			d_dev = it;
106433d6423SLionel Sambuc 			break;
107433d6423SLionel Sambuc 		}
108433d6423SLionel Sambuc 	}
109433d6423SLionel Sambuc 
110433d6423SLionel Sambuc 	if (d_dev == NULL) {
111433d6423SLionel Sambuc 		return;
112433d6423SLionel Sambuc 	}
113433d6423SLionel Sambuc 
114433d6423SLionel Sambuc 	d_usb_driver->disconnect(d_dev);
115433d6423SLionel Sambuc }
116433d6423SLionel Sambuc 
117433d6423SLionel Sambuc /*****************************************************************************
118433d6423SLionel Sambuc  *         ddekit_usb_dev_set_data                                           *
119433d6423SLionel Sambuc  ****************************************************************************/
ddekit_usb_dev_set_data(struct ddekit_usb_dev * dev,void * data)120433d6423SLionel Sambuc int ddekit_usb_dev_set_data(struct ddekit_usb_dev *dev, void *data)
121433d6423SLionel Sambuc {
122433d6423SLionel Sambuc 	dev->data = data;
123433d6423SLionel Sambuc 	return 0;
124433d6423SLionel Sambuc }
125433d6423SLionel Sambuc 
126433d6423SLionel Sambuc /*****************************************************************************
127433d6423SLionel Sambuc  *         ddekit_usb_dev_get_data                                           *
128433d6423SLionel Sambuc  ****************************************************************************/
ddekit_usb_dev_get_data(struct ddekit_usb_dev * dev)129433d6423SLionel Sambuc void *ddekit_usb_dev_get_data(struct ddekit_usb_dev *dev)
130433d6423SLionel Sambuc {
131433d6423SLionel Sambuc 	return dev->data;
132433d6423SLionel Sambuc }
133433d6423SLionel Sambuc 
134433d6423SLionel Sambuc /*****************************************************************************
135433d6423SLionel Sambuc  *         ddekit_usb_submit_urb                                             *
136433d6423SLionel Sambuc  ****************************************************************************/
ddekit_usb_submit_urb(struct ddekit_usb_urb * d_urb)137433d6423SLionel Sambuc int ddekit_usb_submit_urb(struct ddekit_usb_urb *d_urb)
138433d6423SLionel Sambuc {
139433d6423SLionel Sambuc 	int res;
140433d6423SLionel Sambuc 	unsigned urb_size = USB_URBSIZE(d_urb->size, d_urb->number_of_packets);
141433d6423SLionel Sambuc 	/* create mx urb out of d_urb */
142433d6423SLionel Sambuc 	struct usb_urb *mx_urb = (struct usb_urb*)
143433d6423SLionel Sambuc 	    ddekit_simple_malloc(urb_size);
144433d6423SLionel Sambuc 	mx_urb->urb_size = urb_size;
145433d6423SLionel Sambuc 
146433d6423SLionel Sambuc 	mx_urb->dev_id = d_urb->dev->id;
147433d6423SLionel Sambuc 	mx_urb->type = d_urb->type;
148433d6423SLionel Sambuc 	mx_urb->endpoint = d_urb->endpoint;
149433d6423SLionel Sambuc 	mx_urb->direction = d_urb->direction;
150433d6423SLionel Sambuc 	mx_urb->interval = d_urb->interval;
151433d6423SLionel Sambuc 	mx_urb->transfer_flags = d_urb->transfer_flags;
152433d6423SLionel Sambuc 	mx_urb->size = d_urb->size;
153433d6423SLionel Sambuc 	mx_urb->priv = d_urb;
154433d6423SLionel Sambuc 
155433d6423SLionel Sambuc 	if (mx_urb->type == USB_TRANSFER_CTL) {
156433d6423SLionel Sambuc 		memcpy(mx_urb->setup_packet, d_urb->setup_packet, 8);
157433d6423SLionel Sambuc 	}
158433d6423SLionel Sambuc 
159433d6423SLionel Sambuc 	if (mx_urb->type == USB_TRANSFER_ISO) {
160433d6423SLionel Sambuc 		mx_urb->number_of_packets = d_urb->number_of_packets;
161433d6423SLionel Sambuc 		mx_urb->start_frame = d_urb->start_frame;
162433d6423SLionel Sambuc 		memcpy(mx_urb->buffer + d_urb->size, d_urb->iso_desc,
163433d6423SLionel Sambuc 		    d_urb->number_of_packets * sizeof(struct usb_iso_packet_desc));
164433d6423SLionel Sambuc 	}
165433d6423SLionel Sambuc 	memcpy(mx_urb->buffer, d_urb->data, d_urb->size);
166433d6423SLionel Sambuc 
167433d6423SLionel Sambuc 	d_urb->ddekit_priv = mx_urb;
168433d6423SLionel Sambuc 
169433d6423SLionel Sambuc 	/* submit mx_urb */
170433d6423SLionel Sambuc 	res = usb_send_urb(mx_urb);
171433d6423SLionel Sambuc 	return res;
172433d6423SLionel Sambuc }
173433d6423SLionel Sambuc 
174433d6423SLionel Sambuc /*****************************************************************************
175433d6423SLionel Sambuc  *         ddekit_usb_cancle_urb                                             *
176433d6423SLionel Sambuc  ****************************************************************************/
ddekit_usb_cancle_urb(struct ddekit_usb_urb * d_urb)177433d6423SLionel Sambuc int ddekit_usb_cancle_urb(struct ddekit_usb_urb *d_urb)
178433d6423SLionel Sambuc {
179433d6423SLionel Sambuc 	int res;
180433d6423SLionel Sambuc 
181433d6423SLionel Sambuc 	/* get the associated mx_urb */
182433d6423SLionel Sambuc 	struct usb_urb *mx_urb = (struct usb_urb *) d_urb->ddekit_priv;
183433d6423SLionel Sambuc 
184433d6423SLionel Sambuc 	res = usb_cancle_urb(mx_urb);
185433d6423SLionel Sambuc 
186433d6423SLionel Sambuc 	return res;
187433d6423SLionel Sambuc }
188433d6423SLionel Sambuc 
189*2d64210cSWojciech Zajac 
190*2d64210cSWojciech Zajac /*****************************************************************************
191*2d64210cSWojciech Zajac  *         ddekit_usb_info                                                   *
192*2d64210cSWojciech Zajac  *****************************************************************************/
193*2d64210cSWojciech Zajac long
ddekit_usb_info(struct ddekit_usb_dev * UNUSED (dev),long type,long value)194*2d64210cSWojciech Zajac ddekit_usb_info(struct ddekit_usb_dev * UNUSED(dev), long type, long value)
195*2d64210cSWojciech Zajac {
196*2d64210cSWojciech Zajac 	return usb_send_info(type, value);
197*2d64210cSWojciech Zajac }
198*2d64210cSWojciech Zajac 
199*2d64210cSWojciech Zajac 
_ddekit_usb_thread()200433d6423SLionel Sambuc static void _ddekit_usb_thread()
201433d6423SLionel Sambuc {
202433d6423SLionel Sambuc 	struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(USB_BASE,
203433d6423SLionel Sambuc 	                                    USB_BASE + 0x1000);
204433d6423SLionel Sambuc 	message m;
205433d6423SLionel Sambuc 	int ipc_status;
206433d6423SLionel Sambuc 
207433d6423SLionel Sambuc 	while (1) {
208433d6423SLionel Sambuc 		ddekit_minix_rcv(mq, &m, &ipc_status);
209433d6423SLionel Sambuc 		usb_handle_msg(&mx_usb_driver, &m);
210433d6423SLionel Sambuc 	}
211433d6423SLionel Sambuc 
212433d6423SLionel Sambuc }
213433d6423SLionel Sambuc 
214433d6423SLionel Sambuc /*****************************************************************************
215433d6423SLionel Sambuc  *         ddekit_usb_init                                             *
216433d6423SLionel Sambuc  ****************************************************************************/
ddekit_usb_init(struct ddekit_usb_driver * drv,ddekit_usb_malloc_fn * unused,ddekit_usb_free_fn * _unused)217433d6423SLionel Sambuc int ddekit_usb_init
218433d6423SLionel Sambuc (struct ddekit_usb_driver *drv,
219433d6423SLionel Sambuc  ddekit_usb_malloc_fn     *unused,
220433d6423SLionel Sambuc  ddekit_usb_free_fn       *_unused)
221433d6423SLionel Sambuc {
222433d6423SLionel Sambuc 	/* start usb_thread */
223433d6423SLionel Sambuc 	d_usb_driver =  drv;
224433d6423SLionel Sambuc 	usb_init("dde");
225433d6423SLionel Sambuc 	_ddekit_usb_thread();
226433d6423SLionel Sambuc 	return 0;
227433d6423SLionel Sambuc }
228433d6423SLionel Sambuc 
229