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