Subversion Repositories Kolibri OS

Rev

Rev 1875 | Blame | Last modification | View Log | Download | RSS feed

  1.  
  2. #define UHCI_USBLEGSUP          0x00c0  /* legacy support */
  3. #define UHCI_USBLEGSUP_DEFAULT  0x2000  /* only PIRQ enable set */
  4. #define UHCI_USBLEGSUP_RWC      0x8f00  /* the R/WC bits */
  5. #define UHCI_USBLEGSUP_RO       0x5040  /* R/O and reserved bits */
  6.  
  7.  
  8. #define UHCI_USBCMD                  0  /* command register */
  9. #define UHCI_USBINTR                 4  /* interrupt register */
  10. #define UHCI_USBCMD_RUN         0x0001  /* RUN/STOP bit */
  11. #define UHCI_USBCMD_HCRESET     0x0002  /* Host Controller reset */
  12. #define UHCI_USBCMD_EGSM        0x0008  /* Global Suspend Mode */
  13. #define UHCI_USBCMD_CONFIGURE   0x0040  /* Config Flag */
  14. #define UHCI_USBINTR_RESUME     0x0002  /* Resume interrupt enable */
  15.  
  16.  
  17. #define USBCMD                       0
  18. #define  USBCMD_RS              0x0001  /* Run/Stop */
  19. #define  USBCMD_HCRESET         0x0002  /* Host reset */
  20. #define  USBCMD_GRESET          0x0004  /* Global reset */
  21. #define  USBCMD_EGSM            0x0008  /* Global Suspend Mode */
  22. #define  USBCMD_FGR             0x0010  /* Force Global Resume */
  23. #define  USBCMD_SWDBG           0x0020  /* SW Debug mode */
  24. #define  USBCMD_CF              0x0040  /* Config Flag (sw only) */
  25. #define  USBCMD_MAXP            0x0080  /* Max Packet (0 = 32, 1 = 64) */
  26.  
  27. #define  USBSTS                      2
  28. #define   USBSTS_USBINT         0x0001  /* Interrupt due to IOC */
  29. #define   USBSTS_ERROR          0x0002  /* Interrupt due to error */
  30. #define   USBSTS_RD             0x0004  /* Resume Detect */
  31. #define   USBSTS_HSE            0x0008  /* Host System Error: PCI problems */
  32. #define   USBSTS_HCPE           0x0010  /* Host Controller Process Error:
  33.                                          * the schedule is buggy */
  34. #define   USBSTS_HCH            0x0020  /* HC Halted */
  35.  
  36.  
  37. #define  USBFRNUM                    6
  38. #define  USBFLBASEADD                8
  39. #define  USBSOF                     12
  40. #define  USBSOF_DEFAULT             64  /* Frame length is exactly 1 ms */
  41.  
  42. #define  USBPORTSC1                 16
  43. #define  USBPORTSC2                 18
  44.  
  45. #define  UHCI_RH_MAXCHILD            7
  46.  
  47.  
  48. /*
  49.  * Make sure the controller is completely inactive, unable to
  50.  * generate interrupts or do DMA.
  51.  */
  52. void uhci_reset_hc(hc_t *hc)
  53. {
  54.         /* Turn off PIRQ enable and SMI enable.  (This also turns off the
  55.          * BIOS's USB Legacy Support.)  Turn off all the R/WC bits too.
  56.          */
  57.  
  58.    out16(hc->iobase + UHCI_USBCMD, 0);
  59.    out16(hc->iobase + UHCI_USBINTR, 0);
  60.  
  61.    pciWriteWord(hc->PciTag, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC);
  62.  
  63.         /* Reset the HC - this will force us to get a
  64.          * new notification of any already connected
  65.          * ports due to the virtual disconnect that it
  66.          * implies.
  67.          */
  68.    out16(hc->iobase + UHCI_USBCMD, UHCI_USBCMD_HCRESET);
  69.    __asm__ __volatile__ ("":::"memory");
  70.  
  71.    delay(20/10);
  72.  
  73.    if (in16(hc->iobase + UHCI_USBCMD) & UHCI_USBCMD_HCRESET)
  74.        dbgprintf("HCRESET not completed yet!\n");
  75.  
  76.         /* Just to be safe, disable interrupt requests and
  77.          * make sure the controller is stopped.
  78.          */
  79.    out16(hc->iobase + UHCI_USBINTR, 0);
  80.    out16(hc->iobase + UHCI_USBCMD, 0);
  81. };
  82.  
  83. int uhci_check_and_reset_hc(hc_t *hc)
  84. {
  85.    u16_t legsup;
  86.         unsigned int cmd, intr;
  87.  
  88.         /*
  89.          * When restarting a suspended controller, we expect all the
  90.          * settings to be the same as we left them:
  91.          *
  92.          *      PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
  93.          *      Controller is stopped and configured with EGSM set;
  94.          *      No interrupts enabled except possibly Resume Detect.
  95.          *
  96.          * If any of these conditions are violated we do a complete reset.
  97.          */
  98.    legsup = pciReadWord(hc->PciTag, UHCI_USBLEGSUP);
  99.         if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) {
  100.        dbgprintf("%s: legsup = 0x%04x\n",__FUNCTION__, legsup);
  101.                 goto reset_needed;
  102.         }
  103.  
  104.    cmd = in16(hc->iobase + UHCI_USBCMD);
  105.    if ( (cmd & UHCI_USBCMD_RUN) ||
  106.        !(cmd & UHCI_USBCMD_CONFIGURE) ||
  107.        !(cmd & UHCI_USBCMD_EGSM))
  108.    {
  109.        dbgprintf("%s: cmd = 0x%04x\n", __FUNCTION__, cmd);
  110.                 goto reset_needed;
  111.         }
  112.  
  113.    intr = in16(hc->iobase + UHCI_USBINTR);
  114.    if (intr & (~UHCI_USBINTR_RESUME))
  115.    {
  116.        dbgprintf("%s: intr = 0x%04x\n", __FUNCTION__, intr);
  117.                 goto reset_needed;
  118.         }
  119.         return 0;
  120.  
  121. reset_needed:
  122.    dbgprintf("Performing full reset\n");
  123.    uhci_reset_hc(hc);
  124.         return 1;
  125. }
  126.  
  127. int hc_interrupt(void *data)
  128. {
  129.    hc_t   *hc = (hc_t*)data;
  130.  
  131.   // printf("USB interrupt\n");
  132.  
  133.    request_t  *rq;
  134.    u16_t  status;
  135.  
  136.    status = in16(hc->iobase + USBSTS);
  137.    if (!(status & ~USBSTS_HCH))            /* shared interrupt, not mine */
  138.        return 0;
  139.  
  140.    out16(hc->iobase + USBSTS, status);     /* Clear it */
  141.  
  142.    rq = (request_t*)hc->rq_list.next;
  143.  
  144.    while( &rq->list != &hc->rq_list)
  145.    {
  146.        request_t *rtmp;
  147.        td_t      *td;
  148.  
  149.        rtmp = rq;
  150.        rq = (request_t*)rq->list.next;
  151.  
  152.        td  = rtmp->td_tail;
  153.  
  154.        if( td->status & TD_CTRL_ACTIVE)
  155.            continue;
  156.  
  157.        list_del(&rtmp->list);
  158.  
  159.        RaiseEvent(rtmp->evh, 0, &rtmp->event);
  160.    };
  161.  
  162.    return 1;
  163. };
  164.  
  165.  
  166.  
  167. bool init_hc(hc_t *hc)
  168. {
  169.    int    port;
  170.    u32_t  ifl;
  171.    u16_t  dev_status;
  172.    td_t   *td;
  173.    int i;
  174.  
  175.    dbgprintf("\n\ninit uhci %x\n\n", hc->pciId);
  176.  
  177.    for(i=0;i<6;i++)
  178.    {
  179.        if(hc->ioBase[i]){
  180.           hc->iobase = hc->ioBase[i];
  181.       //    dbgprintf("Io base_%d 0x%x\n", i,hc->ioBase[i]);
  182.           break;
  183.        };
  184.    };
  185.  
  186.         /* The UHCI spec says devices must have 2 ports, and goes on to say
  187.          * they may have more but gives no way to determine how many there
  188.          * are.  However according to the UHCI spec, Bit 7 of the port
  189.          * status and control register is always set to 1.  So we try to
  190.          * use this to our advantage.  Another common failure mode when
  191.          * a nonexistent register is addressed is to return all ones, so
  192.          * we test for that also.
  193.          */
  194.    for (port = 0; port < 2; port++)
  195.    {
  196.        u32_t status;
  197.  
  198.        status = in16(hc->iobase + USBPORTSC1 + (port * 2));
  199.        dbgprintf("port%d status %x\n", port, status);
  200.        if (!(status & 0x0080) || status == 0xffff)
  201.                         break;
  202.         }
  203.    dbgprintf("detected %d ports\n\n", port);
  204.  
  205.    hc->numports = port;
  206.  
  207.         /* Kick BIOS off this hardware and reset if the controller
  208.          * isn't already safely quiescent.
  209.          */
  210.     uhci_check_and_reset_hc(hc);
  211.  
  212.     hc->frame_base   = (u32_t*)KernelAlloc(4096);
  213.     hc->frame_dma    = GetPgAddr(hc->frame_base);
  214.     hc->frame_number = 0;
  215.  
  216.     hc->td_pool = dma_pool_create("uhci_td", NULL,
  217.                                   sizeof(td_t), 16, 0);
  218.     if (!hc->td_pool)
  219.     {
  220.         dbgprintf("unable to create td dma_pool\n");
  221.         goto err_create_td_pool;
  222.     }
  223.  
  224.     for (i = 0; i < UHCI_NUM_SKELQH; i++)
  225.     {
  226.     qh_t *qh = alloc_qh();
  227.  
  228.     qh->qlink = 1;
  229.     qh->qelem = 1;
  230.  
  231.         hc->qh[i] = qh;
  232.     }
  233.     for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i)
  234.         hc->qh[i]->qlink = hc->qh[SKEL_ASYNC]->dma | 2;
  235.  
  236.     for (i = 0; i < 1024; i++)
  237.     {
  238.         int qnum;
  239.  
  240.         qnum = 8 - (int) __bsf( i | 1024);
  241.  
  242.         if (qnum <= 1)
  243.             qnum = 9;
  244.  
  245.         hc->frame_base[i] = hc->qh[qnum]->dma | 2;
  246.     }
  247.  
  248.     mb();
  249.  
  250.     /* Set the frame length to the default: 1 ms exactly */
  251.     out8(hc->iobase + USBSOF, USBSOF_DEFAULT);
  252.  
  253.         /* Store the frame list base address */
  254.     out32(hc->iobase + USBFLBASEADD, hc->frame_dma);
  255.  
  256.         /* Set the current frame number */
  257.     out16(hc->iobase + USBFRNUM, 0);
  258.  
  259.     out16(hc->iobase + USBSTS, 0x3F);
  260.  
  261.     out16(hc->iobase + UHCI_USBINTR, 4);
  262.  
  263.     printf("set handler %d  ", hc->irq_line);
  264.     delay(100/10);
  265.     AttachIntHandler(hc->irq_line, hc_interrupt, hc);
  266.     printf("done\n");
  267.  
  268.     delay(100/10);
  269.  
  270.  
  271.     pciWriteWord(hc->PciTag, UHCI_USBLEGSUP, UHCI_USBLEGSUP_DEFAULT);
  272.  
  273.     out16(hc->iobase + USBCMD, USBCMD_RS | USBCMD_CF |
  274.                                USBCMD_MAXP);
  275.  
  276.     for (port = 0; port < hc->numports; ++port)
  277.         out16(hc->iobase + USBPORTSC1 + (port * 2), 0x200);
  278.  
  279.     for (port = 0; port < 2; ++port)
  280.     {
  281.         time_t timeout;
  282.  
  283.         delay(100/10);
  284.  
  285.         u32_t status = in16(hc->iobase + USBPORTSC1 + (port * 2));
  286.         dbgprintf("port%d status %x\n", port, status);
  287.  
  288.         out16(hc->iobase + USBPORTSC1 + (port * 2), 0);
  289.  
  290.         timeout = 100/10;
  291.         while(timeout--)
  292.         {
  293.             delay(10/10);
  294.             status = in16(hc->iobase + USBPORTSC1 + (port * 2));
  295.             if(status & 1)
  296.             {
  297.                 udev_t *dev = kmalloc(sizeof(udev_t),0);
  298.  
  299.                 out16(hc->iobase + USBPORTSC1 + (port * 2), 0x0E);
  300.  
  301.                 delay(20/10);
  302.  
  303.                 dbgprintf("enable port\n");
  304.                 status = in16(hc->iobase + USBPORTSC1 + (port * 2));
  305.                 dbgprintf("port%d status %x\n", port, status);
  306.  
  307.                 INIT_LIST_HEAD(&dev->list);
  308.  
  309.                 dev->host     = hc;
  310.                 dev->port     = port;
  311.                 dev->ep0_size = 8;
  312.                 dev->status   = status;
  313.  
  314.                 dbgprintf("port%d connected", port);
  315.                 if(status & 4)
  316.                     dbgprintf(" enabled");
  317.                 else
  318.                     dbgprintf(" disabled");
  319.                 if(status & 0x100){
  320.                     dev->speed = 0x4000000;
  321.                     dbgprintf(" low speed\n");
  322.                 } else {
  323.                     dev->speed = 0;
  324.                     dbgprintf(" full speed\n");
  325.                 };
  326.  
  327.                 if(set_address(dev)) {
  328.                     list_add_tail(&dev->list, &newdev_list);
  329.                     hc->port_map |= 1<<port;
  330.                 }
  331.                 else {
  332.                     free(dev);
  333.                     out16(hc->iobase + USBPORTSC1 + (port * 2), 0);
  334.                 }
  335.                 break;
  336.             };
  337.         };
  338.     };
  339.     return true;
  340.  
  341. err_create_td_pool:
  342.  
  343.     KernelFree(hc->frame_base);
  344.  
  345.     return false;
  346. };
  347.  
  348. u16_t __attribute__((aligned(16)))
  349.       req_descr[4]  = {0x0680,0x0100,0x0000,8};
  350.  
  351. /*
  352. IN(69) OUT(E1) SETUP(2D)
  353. SETUP(0) IN(1)
  354. SETUP(0) OUT(1) OUT(0) OUT(1)...IN(1)
  355. SETUP(0) IN(1) IN(0) IN(1)...OUT(0)
  356. */
  357.  
  358.  
  359. bool set_address(udev_t *dev)
  360. {
  361.     static  udev_id   = 0;
  362.     static  udev_addr = 0;
  363.     static  u16_t __attribute__((aligned(16)))
  364.             req_addr[4] = {0x0500,0x0001,0x0000,0x0000};
  365.  
  366.     static  u16_t __attribute__((aligned(16)))
  367.             req_descr[4]  = {0x0680,0x0100,0x0000,8};
  368.  
  369.     static  u32_t   data[2] __attribute__((aligned(16)));
  370.  
  371.     qh_t  *qh;
  372.     td_t  *td0, *td1, *td2;
  373.     u32_t   dev_status;
  374.     count_t timeout;
  375.     int address;
  376.  
  377.     address   = ++udev_addr;
  378.  
  379.     req_addr[1] = address;
  380.  
  381.     if( !ctrl_request(dev, &req_addr, DOUT, NULL, 0))
  382.         return false;
  383.  
  384.     dev->addr = address;
  385.     dev->id   = (++udev_id << 8) | address;
  386.  
  387.     dbgprintf("set address %d\n", address);
  388.  
  389.     data[0] = 0;
  390.     data[1] = 0;
  391.  
  392.     if( !ctrl_request(dev, &req_descr, DIN, data, 8))
  393.         return false;
  394.  
  395.     dev_descr_t *descr = (dev_descr_t*)&data;
  396.     dev->ep0_size = descr->bMaxPacketSize0;
  397.  
  398.     return true;
  399. }
  400.  
  401. #define ALIGN16(x) (((x)+15)&~15)
  402.  
  403. #define MakePtr( cast, ptr, addValue ) (cast)((addr_t)(ptr)+(addr_t)(addValue))
  404.  
  405. request_t *alloc_rq_buffer(udev_t *dev, endp_t *enp, u32_t dir,
  406.                            size_t data_size)
  407. {
  408.     size_t  packet_size = dev->ep0_size;
  409.     int     dsize = data_size;
  410.     size_t  buf_size;
  411.  
  412.     addr_t  buf_dma;
  413.     addr_t  td_dma;
  414.     addr_t  data_dma;
  415.  
  416.     request_t *rq;
  417.  
  418.     td_t  *td, *td_prev;
  419.     int td_count = 0;
  420.  
  421.     while(dsize > 0)
  422.     {
  423.         td_count++;
  424.         dsize-= packet_size;
  425.     };
  426.  
  427.     buf_size = ALIGN16(sizeof(request_t)) + ALIGN16(data_size) +
  428.                td_count*sizeof(td_t);
  429.  
  430.     rq = (request_t*)hcd_buffer_alloc(buf_size, &buf_dma);
  431.     memset(rq, 0, buf_size);
  432.  
  433.     data_dma = buf_dma + ALIGN16(sizeof(request_t));
  434.     td_dma = data_dma + ALIGN16(data_size);
  435.  
  436.     INIT_LIST_HEAD(&rq->list);
  437.  
  438.     rq->data = MakePtr(addr_t, rq, ALIGN16(sizeof(request_t)));
  439.     td = MakePtr(td_t*, rq->data, ALIGN16(data_size));
  440.     rq->td_head = td;
  441.     rq->size = data_size;
  442.     rq->dev  = dev;
  443.  
  444.     td_prev = NULL;
  445.  
  446.     dsize = data_size;
  447.  
  448.     while(dsize != 0)
  449.     {
  450.         if ( dsize < packet_size)
  451.         {
  452.             packet_size = dsize;
  453.         };
  454.  
  455.         td->dma = td_dma;
  456.  
  457.         td->link = 1;
  458.  
  459.         if( td_prev )
  460.             td_prev->link   = td->dma | 4;
  461.         td->status = TD_CTRL_ACTIVE | dev->speed;
  462.         td->token  = TOKEN(packet_size,enp->toggle,enp->address,
  463.                            dev->addr,dir);
  464.         td->buffer = data_dma;
  465.         td->bk     = td_prev;
  466.  
  467.         td_prev = td;
  468.  
  469.         td++;
  470.         td_dma+= sizeof(td_t);
  471.         data_dma+= packet_size;
  472.  
  473.         dsize-= packet_size;
  474.         enp->toggle ^= DATA1;
  475.     };
  476.  
  477.     td_prev->status |= TD_CTRL_IOC;
  478.     rq->td_tail = td_prev;
  479.  
  480.     rq->evh = CreateEvent(NULL, MANUAL_DESTROY);
  481.  
  482.     if(rq->evh.handle == 0)
  483.         printf("%s: epic fail\n", __FUNCTION__);
  484.  
  485.     rq->event.code    = 0xFF000001;
  486.     rq->event.data[0] = (addr_t)rq;
  487.  
  488.     return rq;
  489. }
  490.  
  491. bool ctrl_request(udev_t *dev, void *req, u32_t pid,
  492.                   void *data, size_t req_size)
  493. {
  494.     size_t  packet_size = dev->ep0_size;
  495.     size_t  size = req_size;
  496.     u32_t   toggle = DATA1;
  497.  
  498.     td_t   *td0, *td, *td_prev;
  499.     qh_t   *qh;
  500.     addr_t  data_dma = 0;
  501.     hc_t   *hc = dev->host;
  502.  
  503.     addr_t  td_dma = 0;
  504.  
  505.     bool    retval;
  506.  
  507.  
  508.     request_t *rq = (request_t*)kmalloc(sizeof(request_t),0);
  509.  
  510.     INIT_LIST_HEAD(&rq->list);
  511.  
  512.     rq->data = (addr_t)data;
  513.     rq->size = req_size;
  514.     rq->dev  = dev;
  515.  
  516.     td0 = dma_pool_alloc(hc->td_pool, 0, &td_dma);
  517.     td0->dma = td_dma;
  518.  
  519. //    dbgprintf("alloc td0 %x dma %x\n", td0, td_dma);
  520.  
  521.     td0->status = 0x00800000 | dev->speed;
  522.     td0->token  = TOKEN( 8, DATA0, 0, dev->addr, 0x2D);
  523.     td0->buffer = DMA(req);
  524.     td0->bk     = NULL;
  525.  
  526.     if(data)
  527.         data_dma = DMA(data);
  528.  
  529.     td_prev = td0;
  530.  
  531.     while(size > 0)
  532.     {
  533.         if ( size < packet_size)
  534.         {
  535.             packet_size = size;
  536.         };
  537.  
  538.         td = dma_pool_alloc(hc->td_pool, 0, &td_dma);
  539.         td->dma = td_dma;
  540.  
  541. //        dbgprintf("alloc td %x dma %x\n", td, td->dma);
  542.  
  543.         td_prev->link   = td->dma | 4;
  544.         td->status = TD_CTRL_ACTIVE | dev->speed;
  545.         td->token  = TOKEN(packet_size, toggle, 0,dev->addr, pid);
  546.         td->buffer = data_dma;
  547.         td->bk     = td_prev;
  548.  
  549.         td_prev = td;
  550.  
  551.         data_dma+= packet_size;
  552.         size-= packet_size;
  553.         toggle ^= DATA1;
  554.     }
  555.  
  556.     td = dma_pool_alloc(hc->td_pool, 0, &td_dma);
  557.     td->dma = td_dma;
  558.  
  559. //    dbgprintf("alloc td %x dma %x\n", td, td->dma);
  560.  
  561.     td_prev->link   = td->dma | 4;
  562.  
  563.     pid = (pid == DIN) ? DOUT : DIN;
  564.  
  565.     td->link = 1;
  566.     td->status = TD_CTRL_ACTIVE | TD_CTRL_IOC | dev->speed ;
  567.     td->token  = (0x7FF<<21)|DATA1|(dev->addr<<8)|pid;
  568.     td->buffer = 0;
  569.     td->bk     = td_prev;
  570.  
  571.     rq->td_head = td0;
  572.     rq->td_tail = td;
  573.  
  574.     rq->evh = CreateEvent(NULL, MANUAL_DESTROY);
  575.  
  576.     if(rq->evh.handle == 0)
  577.         printf("%s: epic fail\n", __FUNCTION__);
  578.  
  579.     rq->event.code    = 0xFF000001;
  580.     rq->event.data[0] = (addr_t)rq;
  581.  
  582.     u32_t efl = safe_cli();
  583.  
  584.     list_add_tail(&rq->list, &dev->host->rq_list);
  585.  
  586.     qh = dev->host->qh[SKEL_ASYNC];
  587.  
  588.     qh->qelem = td0->dma;
  589.  
  590.     mb();
  591.  
  592.     safe_sti(efl);
  593.  
  594.     WaitEvent(rq->evh);
  595.  
  596.     dbgprintf("td0 status 0x%0x\n", td0->status);
  597.     dbgprintf("td  status 0x%0x\n", td->status);
  598.  
  599.     if( (td0->status & TD_ANY_ERROR) ||
  600.         (td_prev->status & TD_ANY_ERROR) ||
  601.         (td->status & TD_ANY_ERROR))
  602.     {
  603.         u32_t dev_status = in16(dev->host->iobase + USBSTS);
  604.  
  605.         dbgprintf("\nframe %x, cmd %x status %x\n",
  606.                    in16(dev->host->iobase + USBFRNUM),
  607.                    in16(dev->host->iobase + USBCMD),
  608.                     dev_status);
  609.         dbgprintf("td0 status %x\n",td0->status);
  610.         dbgprintf("td_prev status %x\n",td_prev->status);
  611.         dbgprintf("td status %x\n",td->status);
  612.         dbgprintf("qh %x \n", qh->qelem);
  613.  
  614.         retval = false;
  615.     } else retval = true;
  616.  
  617.     qh->qelem = 1;
  618.  
  619.     mb();
  620.  
  621.     do
  622.     {
  623.         td_prev = td->bk;
  624.         dma_pool_free(hc->td_pool, td, td->dma);
  625.         td = td_prev;
  626.     }while( td != NULL);
  627.  
  628. /*
  629.     delete event;
  630. */
  631.     kfree(rq);
  632.  
  633.     return retval;
  634. };
  635.  
  636.  
  637. bool init_device(udev_t *dev)
  638. {
  639.     static  u16_t __attribute__((aligned(16)))
  640.             req_descr[4]  = {0x0680,0x0100,0x0000,18};
  641.  
  642.     static  u16_t __attribute__((aligned(16)))
  643.             req_conf[4]  = {0x0680,0x0200,0x0000,9};
  644.  
  645.     static dev_descr_t __attribute__((aligned(16))) descr;
  646.  
  647.     interface_descr_t *interface;
  648.  
  649.     u32_t  data[8];
  650.  
  651.     u8_t *dptr;
  652.     conf_descr_t      *conf;
  653.  
  654.     dbgprintf("\ninit device %x, host %x, port %d\n\n",
  655.                dev->id, dev->host->pciId, dev->port);
  656.  
  657.     if( !ctrl_request(dev, req_descr, DIN, &descr, 18))
  658.     {
  659.         dbgprintf("%s epic fail\n",__FUNCTION__);
  660.         return;
  661.     };
  662.  
  663.     dev->dev_descr = descr;
  664.  
  665.     dbgprintf("device descriptor:\n\n"
  666.               "bLength             %d\n"
  667.               "bDescriptorType     %d\n"
  668.               "bcdUSB              %x\n"
  669.               "bDeviceClass        %x\n"
  670.               "bDeviceSubClass     %x\n"
  671.               "bDeviceProtocol     %x\n"
  672.               "bMaxPacketSize0     %d\n"
  673.               "idVendor            %x\n"
  674.               "idProduct           %x\n"
  675.               "bcdDevice           %x\n"
  676.               "iManufacturer       %x\n"
  677.               "iProduct            %x\n"
  678.               "iSerialNumber       %x\n"
  679.               "bNumConfigurations  %d\n\n",
  680.               descr.bLength, descr.bDescriptorType,
  681.               descr.bcdUSB,  descr.bDeviceClass,
  682.               descr.bDeviceSubClass, descr.bDeviceProtocol,
  683.               descr.bMaxPacketSize0, descr.idVendor,
  684.               descr.idProduct, descr.bcdDevice,
  685.               descr.iManufacturer, descr.iProduct,
  686.               descr.iSerialNumber, descr.bNumConfigurations);
  687.  
  688.     req_conf[3] = 8;
  689.     if( !ctrl_request(dev, req_conf, DIN, &data, 8))
  690.         return;
  691.  
  692.     conf = (conf_descr_t*)&data;
  693.  
  694.     size_t conf_size = conf->wTotalLength;
  695.  
  696.     req_conf[3] = conf_size;
  697.     conf = malloc(conf_size);
  698.  
  699.     if( !ctrl_request(dev, req_conf, DIN, conf, conf_size))
  700.         return;
  701.  
  702.     dptr = (u8_t*)conf;
  703.     dptr+= conf->bLength;
  704.  
  705.     dbgprintf("configuration descriptor\n\n"
  706.               "bLength             %d\n"
  707.               "bDescriptorType     %d\n"
  708.               "wTotalLength        %d\n"
  709.               "bNumInterfaces      %d\n"
  710.               "bConfigurationValue %x\n"
  711.               "iConfiguration      %d\n"
  712.               "bmAttributes        %x\n"
  713.               "bMaxPower           %dmA\n\n",
  714.               conf->bLength,
  715.               conf->bDescriptorType,
  716.               conf->wTotalLength,
  717.               conf->bNumInterfaces,
  718.               conf->bConfigurationValue,
  719.               conf->iConfiguration,
  720.               conf->bmAttributes,
  721.               conf->bMaxPower*2);
  722.  
  723.         interface = (interface_descr_t*)dptr;
  724.  
  725.         switch(interface->bInterfaceClass)
  726.         {
  727.             case USB_CLASS_AUDIO:
  728.                 dbgprintf( "audio device\n");
  729.                 break;
  730.             case USB_CLASS_HID:
  731.                 dev->conf = conf;
  732.                 list_del(&dev->list);
  733.                 return init_hid(dev);
  734.  
  735.             case USB_CLASS_PRINTER:
  736.                 dbgprintf("printer\n");
  737.                 break;
  738.             case USB_CLASS_MASS_STORAGE:
  739.                 dbgprintf("mass storage device\n");
  740.                 break;
  741.             case USB_CLASS_HUB:
  742.                 dbgprintf("hub device\n");
  743.                 break;
  744.             default:
  745.                 dbgprintf("unknown device\n");
  746.         };
  747. };
  748.