1 /*
2 * USB host chip emulation
3 *
4 * Copyright (c) 2012-2015 David Galvez. ARAnyM development team (see AUTHORS).
5 *
6 * This file is part of the ARAnyM project which builds a new and powerful
7 * TOS/FreeMiNT compatible virtual machine running on almost any hardware.
8 *
9 * ARAnyM is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * ARAnyM is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ARAnyM; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include "sysdeps.h"
25 #include "usbhost.h"
26 #include "../../atari/usbhost/usbhost_nfapi.h"
27
28 #define DEBUG 0
29 #include "debug.h"
30
31 #include "SDL_compat.h"
32 #include <SDL_thread.h>
33
34 /*--- Defines ---*/
35
36 #define EINVFN -32
37
38 #define min1_t(type,x,y) \
39 ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
40
41 /* Galvez: added to avoid the variables being shadowed warning */
42 #define min2_t(type,x,y) \
43 ({ type __a = (x); type __b = (y); __a < __b ? __a : __b; })
44
45 /* USBHOst runs at interrupt level 5 by default but can be reconfigured */
46 #if 0
47 # define INTLEVEL 3
48 # define TRIGGER_INTERRUPT TriggerInt3()
49 #else
50 # define INTLEVEL 5
51 # define TRIGGER_INTERRUPT TriggerInt5()
52 #endif
53
54 /* --- Virtual Root Hub ---------------------------------------------------- */
55
56 /* Device descriptor */
57
58 static uint8 root_hub_dev_des[] = {
59 0x12, /* uint8 bLength; */
60 0x01, /* uint8 bDescriptorType; Device */
61 0x00, /* uint16 bcdUSB; v1.1 */
62 0x02,
63 0x09, /* uint8 bDeviceClass; HUB_CLASSCODE */
64 0x00, /* uint8 bDeviceSubClass; */
65 0x00, /* uint8 bDeviceProtocol; */
66 0x08, /* uint8 bMaxPacketSize0; 8 Bytes */
67 0x00, /* uint16 idVendor; */
68 0x00,
69 0x00, /* uint16 idProduct; */
70 0x00,
71 0x00, /* uint16 bcdDevice; */
72 0x00,
73 0x00, /* uint8 iManufacturer; */
74 0x01, /* uint8 iProduct; */
75 0x00, /* uint8 iSerialNumber; */
76 0x01 /* uint8 bNumConfigurations; */
77 };
78
79 /* Configuration descriptor */
80
81 static uint8 root_hub_config_des[] = {
82 0x09, /* uint8 bLength; */
83 0x02, /* uint8 bDescriptorType; Configuration */
84 0x19, /* uint16 wTotalLength; */
85 0x00,
86 0x01, /* uint8 bNumInterfaces; */
87 0x01, /* uint8 bConfigurationValue; */
88 0x00, /* uint8 iConfiguration; */
89 0x40, /* uint8 bmAttributes;
90 Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
91 0x00, /* uint8 MaxPower; */
92
93 /* interface */
94 0x09, /* uint8 if_bLength; */
95 0x04, /* uint8 if_bDescriptorType; Interface */
96 0x00, /* uint8 if_bInterfaceNumber; */
97 0x00, /* uint8 if_bAlternateSetting; */
98 0x01, /* uint8 if_bNumEndpoints; */
99 0x09, /* uint8 if_bInterfaceClass; HUB_CLASSCODE */
100 0x00, /* uint8 if_bInterfaceSubClass; */
101 0x00, /* uint8 if_bInterfaceProtocol; */
102 0x00, /* uint8 if_iInterface; */
103
104 /* endpoint */
105 0x07, /* uint8 ep_bLength; */
106 0x05, /* uint8 ep_bDescriptorType; Endpoint */
107 0x81, /* uint8 ep_bEndpointAddress; IN Endpoint 1 */
108 0x03, /* uint8 ep_bmAttributes; Interrupt */
109 0x00, /* uint16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
110 0x02,
111 0xff /* uint8 ep_bInterval; 255 ms */
112 };
113
114 /* Standard string descriptors */
115
116 static uint8 root_hub_str_index0[] = {
117 0x04, /* uint8 bLength; */
118 0x03, /* uint8 bDescriptorType; String-descriptor */
119 0x09, /* uint8 lang ID */
120 0x04, /* uint8 lang ID */
121 };
122
123 static uint8 root_hub_str_index1[] = {
124 0x22, /* uint8 bLength; */
125 0x03, /* uint8 bDescriptorType; String-descriptor */
126 'A', /* uint8 Unicode */
127 0, /* uint8 Unicode */
128 'R', /* uint8 Unicode */
129 0, /* uint8 Unicode */
130 'A', /* uint8 Unicode */
131 0, /* uint8 Unicode */
132 'N', /* uint8 Unicode */
133 0, /* uint8 Unicode */
134 'Y', /* uint8 Unicode */
135 0, /* uint8 Unicode */
136 'M', /* uint8 Unicode */
137 0, /* uint8 Unicode */
138 ' ', /* uint8 Unicode */
139 0, /* uint8 Unicode */
140 ' ', /* uint8 Unicode */
141 0, /* uint8 Unicode */
142 'R', /* uint8 Unicode */
143 0, /* uint8 Unicode */
144 'o', /* uint8 Unicode */
145 0, /* uint8 Unicode */
146 'o', /* uint8 Unicode */
147 0, /* uint8 Unicode */
148 't', /* uint8 Unicode */
149 0, /* uint8 Unicode */
150 ' ', /* uint8 Unicode */
151 0, /* uint8 Unicode */
152 'H', /* uint8 Unicode */
153 0, /* uint8 Unicode */
154 'u', /* uint8 Unicode */
155 0, /* uint8 Unicode */
156 'b', /* uint8 Unicode */
157 0, /* uint8 Unicode */
158 };
159
160 /* Class descriptor */
161 static uint8 root_hub_class_des[] = {
162 0x09, /* uint8 bDescLength*/
163 0x29, /* uint8 bDescriptorType: 0x29 for hub */
164 0x02, /* uint8 bNbrPorts: 2 downstream ports */
165 0x09, /* uint16 wHubCharacteristics */
166 /* Bit 0,1: individual port power switching */
167 /* Bit 2: stand alone hub */
168 /* Bit 3,4: individual port overcurrent protection */
169 0x00, /* Bit 8,15: reserved */
170 0xff, /* uint8 bPwrOn2PwrGood */
171 0x00, /* unit8 bHubContrCurrent */
172 0x00, /* uint8 DeviceRemovable */
173 0xff, /* uint8 PortPwrCtrlMask */
174 };
175
176 /* Class status */
177 static uint8 root_hub_class_st[] = {
178 0x00, /* uint16 wHubStatus */
179 /* Bit 0: Local power supply good */
180 /* Bit 1: No overcurrent condition extsts */
181 0x00,
182 0x00, /* uint16 wHubChange */
183 /* Bit 0: No change has occurred to Local Power Status */
184 /* Bit 1: No change has occurred to Local Power Status */
185 0x00,
186 };
187
188 /*--- Global variables ---*/
189
190 virtual_usbdev_t virtual_device[USB_MAX_DEVICE];
191 int number_ports_used;
192 int reset_flag;
193 roothub_t roothub;
194 uint32 port_status[NUMBER_OF_PORTS];
195
196 static libusb_device **devs;
197 static libusb_device *dev;
198 static libusb_device_handle *devh[USB_MAX_DEVICE];
199 static bool init_flag = false;
200
201 /*--- Functions ---*/
202
fill_port_status(unsigned int port_number,bool connected)203 void fill_port_status(unsigned int port_number, bool connected)
204 {
205 D(bug("USBHost: fill_port_status()"));
206
207 if (connected)
208 port_status[port_number] |= RH_PS_CCS; /* Device attached */
209 else
210 port_status[port_number] &= ~RH_PS_CCS; /* Device dettached */
211
212 port_status[port_number] |= RH_PS_CSC; /* connect status change */
213
214 D(bug("USBHost: (After) P%d port_status %x", port_number, port_status[port_number]));
215 }
216
217
usbhost_get_device_list(void)218 int32 usbhost_get_device_list(void)
219 {
220 int idx_dev = 0, idx_virtdev = 0;
221 ssize_t cnt;
222
223 number_ports_used = 0;
224
225 cnt = libusb_get_device_list(NULL, &devs);
226 D(bug("USBHost: Number of USB devices attached to host bus: %d", (int)cnt));
227 if (cnt < 0)
228 return (int32)cnt;
229
230 while ((dev = devs[idx_dev]) != NULL) {
231 int r = libusb_open(dev, &devh[idx_dev]);
232 if (r < 0) {
233 D(bug("USBHost: Failed to open the device %d", idx_dev));
234 goto try_another;
235 }
236 D(bug("USBHost: Device %d opened", idx_dev));
237
238 r = libusb_get_device_descriptor(dev, &virtual_device[idx_virtdev].dev_desc);
239 if (r < 0) {
240 D(bug("USBHost: Unable to get device descriptor %d", r));
241 goto try_another;
242 }
243
244 if (virtual_device[idx_virtdev].dev_desc.bDeviceClass == LIBUSB_CLASS_HUB) {
245 D(bug("USBHost: Device is a HUB"));
246 goto try_another;
247 }
248
249 r = libusb_get_string_descriptor_ascii(
250 devh[idx_dev],
251 virtual_device[idx_virtdev].dev_desc.iProduct,
252 (unsigned char *)virtual_device[idx_virtdev].product_name,
253 MAX_PRODUCT_LENGTH);
254 if (r < 0) {
255 D(bug("USBHost: Unable to get string descriptor %d", r));
256 goto try_another;
257 }
258
259 r = libusb_get_config_descriptor(dev, 0, &virtual_device[idx_virtdev].config_desc);
260 if (r < 0) {
261 D(bug("USBHost: Unable to get configuration descriptor %d", r));
262 goto try_another;
263 }
264 D(bug("USBHost: Number of interfaces %d", virtual_device[idx_virtdev].config_desc->bNumInterfaces));
265
266 virtual_device[idx_virtdev].idx_dev = idx_dev;
267 virtual_device[idx_virtdev].virtdev_available = true;
268 idx_virtdev++;
269 try_another:
270 idx_dev++;
271 }
272
273 return 0;
274 }
275
276
usbhost_release_device(int virtdev_index)277 int usbhost_release_device(int virtdev_index)
278 {
279 D(bug("USBHost: Release device %d", virtdev_index));
280
281 int r = -1;
282 int dev_index, if_index;
283 int port_number;
284 int no_of_ifaces;
285
286 dev_index = virtual_device[virtdev_index].idx_dev;
287 no_of_ifaces = virtual_device[virtdev_index].config_desc->bNumInterfaces;
288
289 for (if_index = 0; if_index < no_of_ifaces; if_index++) {
290 r = libusb_release_interface(devh[dev_index], if_index);
291 if (r < 0) {
292 D(bug("USBHost: Releasing interface %d failed", if_index));
293 }
294 }
295 virtual_device[virtdev_index].connected = false;
296 port_number = virtual_device[virtdev_index].port_number;
297
298 roothub.port[port_number].busy = false;
299 roothub.port[port_number].atari_dev_idx = -1;
300 fill_port_status(port_number, virtual_device[virtdev_index].connected);
301
302 return r;
303 }
304
305
usbhost_free_usb_devices(void)306 void usbhost_free_usb_devices(void)
307 {
308 int i = 0;
309
310 while (devs[i] != NULL) {
311 if (virtual_device[i].connected)
312 usbhost_release_device(i);
313
314 libusb_close(devh[i]);
315 devh[i] = NULL;
316 i++;
317 }
318
319 libusb_free_device_list(devs,0);
320 memset(&virtual_device, 0, USB_MAX_DEVICE * sizeof(virtual_usbdev_t));
321 }
322
323
usbhost_claim_device(int virtdev_index)324 int usbhost_claim_device(int virtdev_index)
325 {
326 D(bug("USBHost: Claim device %d", virtdev_index));
327
328 int r = -1;
329 int dev_index, if_index;
330 int no_of_ifaces;
331
332 dev_index = virtual_device[virtdev_index].idx_dev;
333 no_of_ifaces = virtual_device[virtdev_index].config_desc->bNumInterfaces;
334
335 for (if_index = 0; if_index < no_of_ifaces; if_index++ ) {
336 r = libusb_kernel_driver_active(devh[dev_index], if_index);
337 if (r < 0) {
338 D(bug("USBHost: Checking if kernel driver is active failed. Error %d", r));
339 return -1;
340 }
341
342 if (r == 1) {
343 D(bug("USBHost: Kernel driver active for interface %d", if_index));
344 D(bug("USBHost: Trying to detach it"));
345 r = libusb_detach_kernel_driver(devh[dev_index], if_index);
346 } else goto claim;
347 if (r < 0) {
348 D(bug("USBHost: Driver detaching failed"));
349 return -1;
350 }
351
352 claim: r = libusb_claim_interface(devh[dev_index], if_index);
353 if (r < 0) {
354 D(bug("USBHost: Claiming interface number %d failed", if_index));
355 }
356 }
357
358 virtual_device[virtdev_index].connected = true;
359
360 for (int i = 0; i < NUMBER_OF_PORTS; i++) {
361 if (roothub.port[i].busy == true)
362 continue;
363 roothub.port[i].busy = true;
364 roothub.port[i].port_number = i;
365 roothub.port[i].libusb_dev_idx = dev_index;
366 virtual_device[virtdev_index].port_number = i;
367 break;
368 }
369
370 fill_port_status(virtual_device[virtdev_index].port_number, virtual_device[virtdev_index].connected);
371
372 return r;
373 }
374
375
print_devs(libusb_device ** devs)376 void print_devs(libusb_device **devs)
377 {
378 libusb_device *dev;
379 int i = 0;
380
381 while ((dev = devs[i++]) != NULL) {
382 struct libusb_device_descriptor desc;
383 int r = libusb_get_device_descriptor(dev, &desc);
384 if (r < 0) {
385 panicbug("USBHost: failed to get device descriptor");
386 return;
387 }
388
389 printf("USBHost: %04x:%04x (bus %d, device %d)\n",
390 desc.idVendor, desc.idProduct,
391 libusb_get_bus_number(dev), libusb_get_device_address(dev));
392 }
393 }
394
395
trigger_interrupt(void *)396 int trigger_interrupt(void *)
397 {
398 D(bug("USBHost: send interrupt"));
399
400 for (;;) {
401 for (int port_number = 0; port_number < NUMBER_OF_PORTS; port_number++) {
402 if ((port_status[port_number] & RH_PS_CSC)) {
403 TRIGGER_INTERRUPT;
404 D(bug("USBHost: trigger interrupt. port_status[%d] %x", port_number, port_status[port_number]));
405 }
406 }
407
408 SDL_Delay(250);
409 }
410
411 return 0;
412 }
413
414
usbhost_init_libusb(void)415 void usbhost_init_libusb(void)
416 {
417 if (init_flag)
418 return;
419
420 if (libusb_init(NULL)) {
421 D(bug("USBHost: Imposible to start libusb"));
422 return;
423 }
424
425 libusb_set_debug(NULL, 3);
426
427 for (int i = 0; i < USB_MAX_DEVICE; i++) {
428 virtual_device[i].connected = false;
429 virtual_device[i].virtdev_available = false;
430 }
431
432 for (int i = 0; i < NUMBER_OF_PORTS; i++) {
433 roothub.port[i].libusb_dev_idx = 0;
434 roothub.port[i].atari_dev_idx = -1;
435 }
436
437 SDL_CreateNamedThread(trigger_interrupt, "USB", NULL);
438
439 usbhost_get_device_list();
440
441 init_flag = true;
442 }
443
444 /*--- Private functions ---*/
445
446 /*--- Support functions ---*/
447
aranym_submit_rh_msg(uint32 pipe,memptr buffer,int32 transfer_len,devrequest * cmd)448 int32 USBHost::aranym_submit_rh_msg(uint32 pipe, memptr buffer, int32 transfer_len,
449 devrequest *cmd)
450 {
451 D(bug("USBHost: aranym_submit_rh_msg()"));
452
453 int32 leni = transfer_len;
454 int32 len = 0;
455 uint32 datab[4];
456 uint8 *data_buf = (uint8 *) datab;
457 int32 stat = 0;
458
459 uint16 bmRType_bReq;
460 uint16 wValue;
461 uint16 wIndex;
462 uint16 wLength;
463
464 if (usb_pipeint(pipe)) {
465 D(bug("USBHost: Root-Hub submit IRQ: NOT implemented"));
466 return -1;
467 }
468
469 bmRType_bReq = cmd->requesttype | (cmd->request << 8);
470 wValue = cmd->value;
471 wIndex = cmd->index;
472 wLength = cmd->length;
473
474 D(bug("USBHost: --- HUB ----------------------------------------"));
475 D(bug("USBHost: submit rh urb, req=%x val=%#x index=%#x len=%d",
476 bmRType_bReq, wValue, wIndex, wLength));
477 D(bug("USBHost: ------------------------------------------------"));
478
479 switch (bmRType_bReq) {
480 case RH_GET_STATUS:
481 D(bug("USBHost: RH_GET_STATUS"));
482 *data_buf = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ?
483 (uint16) SDL_Swap16(1) : (uint16)(1) ;
484 len = 2;
485 break;
486
487 case RH_GET_STATUS | RH_INTERFACE:
488 D(bug("USBHost: RH_GET_STATUS | RH_INTERFACE"));
489 *data_buf = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ?
490 (uint16) SDL_Swap16(0) : (uint16)(0) ;
491 len = 2;
492 break;
493
494 case RH_GET_STATUS | RH_ENDPOINT:
495 D(bug("USBHost: RH_GET_STATUS | RH_ENDPOINT"));
496 *data_buf = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ?
497 (uint16) SDL_Swap16(0) : (uint16)(0) ;
498 len = 2;
499 break;
500
501 case RH_GET_STATUS | RH_CLASS:
502 D(bug("USBHost: RH_GET_STATUS | RH_CLASS"));
503 data_buf = root_hub_class_st;
504 len = 4;
505 break;
506
507 case RH_GET_STATUS | RH_OTHER | RH_CLASS:
508 D(bug("USBHost: RH_GET_STATUS | RH_OTHER | RH_CLASS"));
509 *(uint32 *)data_buf = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ?
510 SDL_Swap32(port_status[wIndex - 1]) :
511 port_status[wIndex - 1];
512 len = 4;
513 break;
514
515 case RH_CLEAR_FEATURE | RH_ENDPOINT:
516 D(bug("USBHost: RH_CLEAR_FEATURE | RH_ENDPOINT"));
517 switch (wValue) {
518 case RH_ENDPOINT_STALL:
519 D(bug("USBHost: C_HUB_ENDPOINT_STALL"));
520 len = 0;
521 break;
522 }
523 break;
524
525 case RH_CLEAR_FEATURE | RH_CLASS:
526 D(bug("USBHost: RH_CLEAR_FEATURE | RH_CLASS"));
527 switch (wValue) {
528 case RH_C_HUB_LOCAL_POWER:
529 D(bug("USBHost: C_HUB_LOCAL_POWER"));
530 len = 0;
531 break;
532
533 case RH_C_HUB_OVER_CURRENT:
534 D(bug("USBHost: C_HUB_OVER_CURRENT"));
535 len = 0;
536 break;
537 }
538 break;
539
540 case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
541 D(bug("USBHost: RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS"));
542 switch (wValue) {
543 case RH_PORT_ENABLE:
544 port_status[wIndex - 1] &= ~RH_PS_PES;
545 len = 0;
546 break;
547
548 case RH_PORT_SUSPEND:
549 port_status[wIndex - 1] |= RH_PS_PSS;
550 len = 0;
551 break;
552
553 case RH_PORT_POWER:
554 len = 0;
555 break;
556
557 case RH_C_PORT_CONNECTION:
558 port_status[wIndex - 1] &= ~RH_PS_CSC;
559 len = 0;
560 break;
561
562 case RH_C_PORT_ENABLE:
563 port_status[wIndex - 1] &= ~RH_PS_PESC;
564 len = 0;
565 break;
566
567 case RH_C_PORT_SUSPEND:
568 len = 0;
569 break;
570
571 case RH_C_PORT_OVER_CURRENT:
572 port_status[wIndex - 1] &= ~RH_PS_OCIC;
573 len = 0;
574 break;
575
576 case RH_C_PORT_RESET:
577 port_status[wIndex - 1] &= ~RH_PS_PRSC;
578 len = 0;
579 break;
580
581 default:
582 D(bug("USBHost: invalid wValue"));
583 stat = USB_ST_STALLED;
584 }
585 break;
586
587 case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
588 D(bug("USBHost: RH_SET_FEATURE | RH_OTHER | RH_CLASS"));
589 switch (wValue) {
590 case RH_PORT_SUSPEND:
591 len = 0;
592 break;
593
594 case RH_PORT_RESET:
595 port_status[wIndex - 1] |= RH_PS_PRS;
596 len = 0;
597 break;
598
599 case RH_PORT_POWER:
600 port_status[wIndex - 1] |= RH_PS_PPS;
601 len = 0;
602 break;
603
604 case RH_PORT_ENABLE:
605 len = 0;
606 break;
607
608 default:
609 D(bug("USBHost: invalid wValue"));
610 stat = USB_ST_STALLED;
611 }
612 break;
613
614 case RH_SET_ADDRESS:
615 D(bug("USBHost: RH_SET_ADDRESS"));
616 rh_devnum = wValue;
617 len = 0;
618 break;
619
620 case RH_GET_DESCRIPTOR:
621 D(bug("USBHost: RH_GET_DESCRIPTOR: %x, %d", wValue, wLength));
622 switch (wValue) {
623 case (USB_DT_DEVICE << 8): /* device descriptor */
624 len = min1_t(uint32, leni,
625 min2_t(uint32, sizeof(root_hub_dev_des), wLength));
626 data_buf = root_hub_dev_des;
627 break;
628
629 case (USB_DT_CONFIG << 8): /* configuration descriptor */
630 len = min1_t(uint32, leni,
631 min2_t(uint32, sizeof(root_hub_config_des), wLength));
632 data_buf = root_hub_config_des;
633 break;
634
635 case ((USB_DT_STRING << 8) | 0x00): /* string 0 descriptors */
636 len = min1_t(uint32, leni,
637 min2_t(uint32, sizeof(root_hub_str_index0), wLength));
638 data_buf = root_hub_str_index0;
639 break;
640
641 case ((USB_DT_STRING << 8) | 0x01): /* string 1 descriptors */
642 len = min1_t(uint32, leni,
643 min2_t(uint32, sizeof(root_hub_str_index1), wLength));
644 data_buf = root_hub_str_index1;
645 break;
646
647 default:
648 D(bug("USBHost: invalid wValue"));
649
650 stat = USB_ST_STALLED;
651 }
652 break;
653
654 case RH_GET_DESCRIPTOR | RH_CLASS:
655 D(bug("USBHost: RH_GET_DESCRIPTOR | RH_CLASS"));
656
657 data_buf = root_hub_class_des;
658 len = min1_t(uint32, leni,
659 min2_t(uint32, data_buf[0], wLength));
660 break;
661
662 case RH_GET_CONFIGURATION:
663 D(bug("USBHost: RH_GET_CONFIGURATION"));
664 *(uint8 *) data_buf = 0x01;
665 len = 1;
666 break;
667
668 case RH_SET_CONFIGURATION:
669 D(bug("USBHost: RH_SET_CONFIGURATION"));
670 len = 0;
671 break;
672
673 default:
674 D(bug("USBHost: *** *** *** unsupported root hub command *** *** ***"));
675 stat = USB_ST_STALLED;
676 }
677
678 len = min1_t(uint32, len, leni);
679
680 if(buffer != 0)
681 Host2Atari_memcpy(buffer, data_buf, len);
682
683 return (stat ? -1 : len);
684 }
685
686
rh_port_status(memptr rh)687 int32 USBHost::rh_port_status(memptr rh)
688 {
689 for (int i = 0; i < NUMBER_OF_PORTS; i++) {
690 WriteInt32(rh + 4 * i, port_status[i]);
691 }
692
693 return 0;
694 }
695
696
697 /*--- API USB functions ---*/
698
usb_lowlevel_init(void)699 int32 USBHost::usb_lowlevel_init(void)
700 {
701 D(bug("\nUSBHost: usb_lowlevel_init()"));
702
703 rh_devnum = 0;
704
705 reset();
706
707 return 0;
708 }
709
710
usb_lowlevel_stop(void)711 int32 USBHost::usb_lowlevel_stop(void)
712 {
713 D(bug("\nUSBHost: usb_lowlevel_stop()"));
714
715 return 0;
716 }
717
718
submit_control_msg(uint32 pipe,memptr buffer,int32 len,memptr devrequest)719 int32 USBHost::submit_control_msg(uint32 pipe, memptr buffer,
720 int32 len, memptr devrequest)
721 {
722 D(bug("\nUSBHost: submit_control_msg()"));
723
724 struct devrequest *cmd;
725 uint8 *tempbuff;
726
727 int32 r = -1;
728 unsigned int dev_idx = 0;
729 int i;
730
731 uint16 bmRType;
732 uint16 bReq;
733 uint16 wValue;
734 uint16 wIndex;
735 uint16 wLength;
736
737 cmd = (struct devrequest *)Atari2HostAddr(devrequest);
738 tempbuff = (uint8 *) Atari2HostAddr(buffer);
739
740 int32 devnum = usb_pipedevice(pipe);
741 D(bug("USBHost: devnum %d ", devnum));
742
743 /* Control message is for the HUB? */
744 if (devnum == rh_devnum)
745 return aranym_submit_rh_msg(pipe, buffer, len, cmd);
746
747 bmRType = cmd->requesttype;
748 bReq = cmd->request;
749 wValue = cmd->value;
750 wIndex = cmd->index;
751 wLength = cmd->length;
752
753 D(bug("USBHost: bmRType %x, bReq %x, wValue %x, wIndex %x, wLength %x", bmRType, bReq, wValue, wIndex, wLength));
754
755 /* Don't allow to change device's addresses set by the host OS */
756 if (bReq == USB_REQ_SET_ADDRESS) {
757 for (i = 0; i < NUMBER_OF_PORTS; i++) {
758 /*
759 * We need to be careful to don't assign to an empty port an already connected
760 * device during the virtual machine reboot. For this we've created the reset_flag
761 * which indicates that we are setting USB devices during a reboot scenario.
762 */
763 if (((roothub.port[i].atari_dev_idx < 0) && !reset_flag) || ((roothub.port[i].atari_dev_idx >= 0) && reset_flag)) {
764 roothub.port[i].atari_dev_idx = wValue;
765 if (reset_flag)
766 reset_flag = 0;
767 break;
768 }
769 }
770 D(bug("USBHost: Attempt to set device address"));
771 r = 0;
772 }
773 else if ((bReq == USB_REQ_SET_CONFIGURATION) && (wValue > 1)) { /* We only support one configuration per device */
774 D(bug("USBHost: Attempt to change to configuration number %d ", wValue));
775 r = -1;
776 }
777 else {
778 for (i = 0; i < NUMBER_OF_PORTS; i++) {
779 if (roothub.port[i].atari_dev_idx == devnum) {
780 dev_idx = roothub.port[i].libusb_dev_idx;
781 D(bug("USBHost: dev_idx %d ", dev_idx));
782 break;
783 }
784 }
785 r = libusb_control_transfer(devh[dev_idx], bmRType, bReq, wValue, wIndex, tempbuff, wLength, 0);
786 D(bug("USBHost: bytes transmitted %d ", r));
787 }
788
789 return r;
790 }
791
792
submit_int_msg(uint32,memptr,int32,int32)793 int32 USBHost::submit_int_msg(uint32 /* pipe */, memptr /* buffer */,
794 int32 /* len*/, int32 /* interval*/)
795 {
796 D(bug("\nUSBHost: submit_int_msg()"));
797 D(bug("\nUSBHost: Function not supported yet"));
798
799 return -1;
800 }
801
802
submit_bulk_msg(uint32 pipe,memptr buffer,int32 len)803 int32 USBHost::submit_bulk_msg(uint32 pipe, memptr buffer, int32 len)
804 {
805 D(bug("\nUSBHost: submit_bulk_msg()"));
806
807 uint8 *tempbuff;
808
809 int32 dir_out;
810 uint8 endpoint;
811 int32 devnum;
812 int32 transferred;
813 unsigned int dev_idx = 0;
814 int i;
815 int32 r;
816
817 tempbuff = (uint8 *)Atari2HostAddr(buffer);
818
819 dir_out = usb_pipeout(pipe);
820 endpoint = usb_pipeendpoint(pipe) | (dir_out ? LIBUSB_ENDPOINT_OUT : LIBUSB_ENDPOINT_IN);
821 devnum = usb_pipedevice(pipe);
822 D(bug("USBHost: devnum %d ", devnum));
823 D(bug("USBHost: pipe %x ", pipe));
824 D(bug("USBHost: --- BULK -----------------------------------------------"));
825 D(bug("USBHost: dev=%d endpoint=%d endpoint address= %x buf=%p size=%d dir_out=%d",
826 usb_pipedevice(pipe), usb_pipeendpoint(pipe), endpoint, tempbuff, len, dir_out));
827
828 for (i = 0; i < NUMBER_OF_PORTS; i++) {
829 if (roothub.port[i].atari_dev_idx == devnum) {
830 dev_idx = roothub.port[i].libusb_dev_idx;
831 D(bug("USBHost: dev_idx %d ", dev_idx));
832 break;
833 }
834 }
835
836 r = libusb_bulk_transfer(devh[dev_idx], endpoint, tempbuff, len, &transferred, 1000);
837 D(bug("USBHost: return: %d len: %d transferred: %d", r, len, transferred));
838
839 return r;
840 }
841
842 /*--- Public functions ---*/
843
844 /* reset, called upon OS reboot */
reset()845 void USBHost::reset()
846 {
847 D(bug("USBHost: reset"));
848
849 for (int i = 0; i < NUMBER_OF_PORTS; i++) {
850 port_status[i] |= (RH_PS_PPS | RH_PS_PES);
851 if (port_status[i] & RH_PS_CCS) {
852 reset_flag = 1;
853 port_status[i] |= RH_PS_CSC;
854 }
855 }
856 }
857
858 /*--- Dispatcher ---*/
dispatch(uint32 fncode)859 int32 USBHost::dispatch(uint32 fncode)
860 {
861 int32 ret;
862
863 D(bug("USBHost: dispatch(%u)", fncode));
864 ret = EINVFN;
865
866 switch(fncode) {
867 case GET_VERSION:
868 D(bug("USBHost: getVersion"));
869 ret = USBHOST_NFAPI_VERSION;
870 break;
871
872 case USBHOST_INTLEVEL:
873 D(bug("USBHost: getINTlevel"));
874 ret = INTLEVEL;
875 break;
876
877 case USBHOST_RH_PORT_STATUS:
878 ret = rh_port_status(getParameter(0));
879 break;
880
881 case USBHOST_LOWLEVEL_INIT:
882 ret = usb_lowlevel_init();
883 break;
884
885 case USBHOST_LOWLEVEL_STOP:
886 ret = usb_lowlevel_stop();
887 break;
888
889 case USBHOST_SUBMIT_CONTROL_MSG:
890 ret = submit_control_msg(getParameter(0), getParameter(1), getParameter(2),
891 getParameter(3));
892 break;
893
894 case USBHOST_SUBMIT_INT_MSG:
895 ret = submit_int_msg(getParameter(0), getParameter(1), getParameter(2),
896 getParameter(3));
897 break;
898
899 case USBHOST_SUBMIT_BULK_MSG:
900 ret = submit_bulk_msg(getParameter(0), getParameter(1), getParameter(2));
901 break;
902 default:
903 D(bug("USBHost: unimplemented function #%d", fncode));
904 break;
905 }
906
907 D(bug("USBHost: function returning with 0x%08x", ret));
908
909 return ret;
910 }
911
912
913 /*--- Constructor/destructor functions ---*/
914
USBHost()915 USBHost::USBHost()
916 {
917 for (int i = 0; i < NUMBER_OF_PORTS; i++) {
918 port_status[i] = 0x0000; /* Clean before use */
919 }
920 D(bug("USBHost: created"));
921 }
922
923
~USBHost()924 USBHost::~USBHost()
925 {
926 int i = USB_MAX_DEVICE - 1;
927 unsigned int port_number = 0;
928
929 if (init_flag) {
930 while (i >= 0) {
931 if (devh[i] != NULL) {
932 D(bug("USBHost: Trying to close device %d", i));
933
934 while (port_number < NUMBER_OF_PORTS) {
935 if (roothub.port[port_number].libusb_dev_idx == i) {
936 if (libusb_release_interface(devh[i], roothub.port[port_number].interface) < 0) {
937 D(bug("USBHost: unable to release device interface"));
938 }
939 if (libusb_attach_kernel_driver(devh[i], roothub.port[port_number].interface) < 0) {
940 D(bug("USBHost: unable to reattach kernel driver to interface"));
941 }
942 break;
943 }
944 port_number++;
945 }
946 libusb_close(devh[i]);
947 devh[i] = NULL;
948 D(bug("USBHost: %d device closed", i));
949 }
950 i--;
951 }
952
953 usbhost_free_usb_devices();
954 libusb_exit(NULL);
955 }
956
957 D(bug("USBHost: destroyed"));
958 }
959
960