Changeset 23328

Show
Ignore:
Timestamp:
01/09/08 14:46:54 (11 months ago)
Author:
stippi
Message:

mmlr+stippi+axeld:
* changed the way the interrupt schedules and repeats are handled, the

input server thread (via ioctl) is now triggering the scheduling and
processing of usb interrupt transfers. As long as it is blocking on
the usb_callback semaphore, it is using it as timeout for the key
repeats.

-> no more deadlock because the driver is issuing usb commands from

within the usb_callback function (hotplugging should be fixed
when using the Haiku usb stack)

-> the driver is no longer installing one timer per key down event
-> simplifications

Location:
haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/hid.c

    r22305 r23328  
    340340        device->open_fds = NULL; 
    341341        device->active = true; 
    342         device->unplugged = false; 
     342        device->transfer_scheduled = false; 
    343343        device->insns = NULL; 
    344344        device->num_insns = 0; 
     
    356356        device->repeat_rate = 35000; 
    357357        device->repeat_delay = 300000; 
    358         device->repeat_timer.device = device; 
    359358 
    360359        return device; 
     
    366365{ 
    367366        assert(device != NULL); 
    368         cancel_timer(&device->repeat_timer.timer); 
    369367 
    370368        if (device->rbuf != NULL) { 
     
    389387 
    390388        ring_buffer_write(device->rbuf, (const uint8*)&raw, sizeof(raw_key_info)); 
    391         release_sem_etc(device->sem_cb, 1, B_DO_NOT_RESCHEDULE); 
    392 } 
    393  
    394  
    395 static int32 
    396 timer_repeat_hook(struct timer *timer) 
    397 { 
    398         hid_device_info *device = ((struct hid_repeat_timer *)timer)->device; 
    399  
    400         write_key(device, device->repeat_timer.key, true); 
    401         return B_HANDLED_INTERRUPT; 
    402 } 
    403  
    404  
    405 static int32 
    406 timer_delay_hook(struct timer *timer) 
    407 { 
    408         hid_device_info *device = ((struct hid_repeat_timer *)timer)->device; 
    409  
    410         add_timer(&device->repeat_timer.timer, timer_repeat_hook, device->repeat_rate, 
    411                 B_PERIODIC_TIMER); 
    412         return B_HANDLED_INTERRUPT; 
    413389} 
    414390 
     
    458434 
    459435                                // repeat handling 
    460                                 cancel_timer(&device->repeat_timer.timer); 
    461436                                device->repeat_timer.key = key; 
    462                                 add_timer(&device->repeat_timer.timer, timer_delay_hook, 
    463                                         device->repeat_delay, B_ONE_SHOT_RELATIVE_TIMER); 
     437                                device->repeat_timer.current_delay = device->repeat_delay; 
    464438                        } 
    465439                } else 
     
    493467 
    494468                                write_key(device, key, false); 
     469 
     470                                // cancel the repeats if they are for this key 
    495471                                if (device->repeat_timer.key == key) 
    496                                         cancel_timer(&device->repeat_timer.timer); 
     472                                        device->repeat_timer.current_delay = B_INFINITE_TIMEOUT; 
    497473                        } 
    498474                } else 
     
    591567        info.timestamp = device->timestamp; 
    592568        ring_buffer_write(device->rbuf, (const uint8*)&info, sizeof(info)); 
    593         release_sem_etc(device->sem_cb, 1, B_DO_NOT_RESCHEDULE); 
    594 } 
     569} 
     570 
     571// #pragma mark - interrupt transfers 
    595572 
    596573 
     
    603580{ 
    604581        hid_device_info *device = cookie; 
    605         status_t status; 
    606  
    607         if (device == NULL || device->unplugged) 
    608                 return; 
    609  
    610         acquire_sem(device->sem_lock); 
     582 
    611583        device->actual_length = actualLength; 
    612584        device->bus_status = busStatus; /* B_USB_STATUS_* */ 
    613         if (busStatus != B_OK) { 
     585 
     586        // release the notification semaphore so the input_server 
     587        // thread which is blocking in hid_device_control can continue 
     588        // to run (see you in handle_interrupt_transfer()) 
     589        release_sem_etc(device->sem_cb, 1, B_DO_NOT_RESCHEDULE); 
     590} 
     591 
     592static status_t 
     593schedule_interrupt_transfer(hid_device_info* device) 
     594{ 
     595        status_t status = usb->queue_interrupt(device->ept->handle, device->buffer, 
     596                device->total_report_size, usb_callback, device); 
     597        if (status != B_OK) { 
     598                /* XXX probably endpoint stall */ 
     599                DPRINTF_ERR ((MY_ID "queue_interrupt() error %d\n", (int)status)); 
     600        } 
     601        return status; 
     602} 
     603 
     604static status_t 
     605handle_interrupt_transfer(hid_device_info* device) 
     606{ 
     607        status_t status = device->bus_status; 
     608 
     609        if (status != B_OK) { 
    614610                /* request failed */ 
    615                 release_sem(device->sem_lock); 
    616                 DPRINTF_ERR((MY_ID "bus status %d\n", (int)busStatus)); 
    617                 if (busStatus == B_CANCELED) { 
     611                DPRINTF_ERR((MY_ID "bus status %d\n", (int)device->bus_status)); 
     612                if (status == B_CANCELED) { 
    618613                        /* cancelled: device is unplugged */ 
    619                         return; 
     614                        return status; 
    620615                } 
    621616#if 1 
     
    642637                } else 
    643638                        interpret_mouse_buffer(device); 
    644                  
    645                 release_sem(device->sem_lock); 
    646         } 
    647  
    648         /* issue next request */ 
    649  
    650         status = usb->queue_interrupt(device->ept->handle, device->buffer, 
    651                 device->total_report_size, usb_callback, device); 
    652         if (status != B_OK) { 
    653                 /* XXX probably endpoint stall */ 
    654                 DPRINTF_ERR ((MY_ID "queue_interrupt() error %d\n", (int)status)); 
    655         } 
     639        } 
     640 
     641        return status; 
    656642} 
    657643 
     
    842828        DPRINTF_INFO ((MY_ID "%08lx %08lx %08lx\n", *(((uint32*)device->buffer)), *(((uint32*)device->buffer)+1), *(((uint32*)device->buffer)+2))); 
    843829 
    844         /* issue interrupt transfer */ 
    845  
    846830        device->ept = &intf->endpoint[0];               /* interrupt IN */ 
    847         status = usb->queue_interrupt(device->ept->handle, device->buffer, 
    848                 device->total_report_size, usb_callback, device); 
    849         if (status != B_OK) { 
    850                 DPRINTF_ERR ((MY_ID "queue_interrupt() error %d\n", (int)status)); 
    851                 return B_ERROR; 
    852         } 
    853831 
    854832        /* create a port */ 
     
    871849        DPRINTF_INFO((MY_ID "device_removed(%s)\n", device->name)); 
    872850         
    873         device->unplugged = true; 
    874851        usb->cancel_queued_transfers (device->ept->handle); 
    875852        remove_device_info(device); 
     
    951928                switch (op) { 
    952929                        case KB_READ: 
    953                         err = acquire_sem_etc(device->sem_cb, 1, B_CAN_INTERRUPT, 0LL); 
    954                         if (err != B_OK) 
    955                                         return err; 
    956                                 acquire_sem(device->sem_lock); 
     930                                while (ring_buffer_readable(device->rbuf) == 0) { 
     931                                        if (!device->transfer_scheduled) { 
     932                                                err = schedule_interrupt_transfer(device); 
     933                                                if (err != B_OK) 
     934                                                        return err; 
     935                                                device->transfer_scheduled = true; 
     936                                                // NOTE: this thread is now blocking until 
     937                                                // the semaphore will be released from the 
     938                                                // call_back function 
     939                                        } 
     940 
     941                                err = acquire_sem_etc(device->sem_cb, 1, 
     942                                        B_CAN_INTERRUPT | B_RELATIVE_TIMEOUT, 
     943                                        device->repeat_timer.current_delay); 
     944                                if (err == B_TIMED_OUT) { 
     945                                        // this case is for handling key repeats, it means 
     946                                        // no interrupt transfer has happened 
     947                                        write_key(device, device->repeat_timer.key, true); 
     948                                        // the next timeout is reduced to the repeat_rate 
     949                                        device->repeat_timer.current_delay = device->repeat_rate; 
     950                                } else if (err == B_OK) { 
     951                                        // this case is for when an actual interrupt transfer 
     952                                        // happened, it is the only possible reason to be here 
     953                                                device->transfer_scheduled = false; 
     954                                                err = handle_interrupt_transfer(device); 
     955                                                if (err != B_OK) 
     956                                                        return err; 
     957                                } else { 
     958                                                return err; 
     959                                } 
     960                                } 
     961 
     962                                // process what is in the ring_buffer, it could be written 
     963                                // there because we handled an interrupt transfer or because 
     964                                // we wrote the current repeat key 
    957965                                ring_buffer_user_read(device->rbuf, arg, sizeof(raw_key_info)); 
    958                                 release_sem(device->sem_lock); 
    959                                 return err; 
    960                                 break; 
     966                                return B_OK; 
    961967             
    962968                        case KB_SET_LEDS: 
     
    967973                switch (op) { 
    968974                        case MS_READ: 
     975                                err = schedule_interrupt_transfer(device); 
     976                                if (err != B_OK) 
     977                                        return err; 
     978                                // NOTE: this thread is now blocking until 
     979                                // the semaphore will be released from the 
     980                                // call_back function 
     981 
    969982                                err = acquire_sem_etc(device->sem_cb, 1, B_CAN_INTERRUPT, 0LL); 
    970983                        if (err != B_OK) 
    971984                                        return err; 
     985 
     986                                err = handle_interrupt_transfer(device); 
     987                                if (err != B_OK) 
     988                                        return err; 
     989 
    972990                                acquire_sem(device->sem_lock); 
    973991                                ring_buffer_user_read(device->rbuf, arg, sizeof(mouse_movement)); 
  • haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/hid.h

    r22305 r23328  
    4646 
    4747struct hid_repeat_timer { 
    48         struct timer timer; 
    49         struct hid_device_info *device; 
     48        bigtime_t current_delay; 
    5049        uint32 key; 
    5150}; 
     
    6968 
    7069        bool active; 
    71         bool unplugged; 
    7270        int open; 
    7371        struct driver_cookie *open_fds; 
     
    7775        int actual_length; 
    7876        const usb_endpoint_info *ept; 
     77        bool transfer_scheduled; 
    7978 
    8079        report_insn     *insns;