Beispiel #1
0
static void* _setupusb(void* context){
    usbdevice* kb = context;
    // Set standard fields
    short vendor = kb->vendor, product = kb->product;
    const devcmd* vt = kb->vtable = get_vtable(vendor, product);
    kb->features = (IS_RGB(vendor, product) ? FEAT_STD_RGB : FEAT_STD_NRGB) & features_mask;
    if(IS_MOUSE(vendor, product)) kb->features |= FEAT_ADJRATE;
    if(IS_MONOCHROME(vendor, product)) kb->features |= FEAT_MONOCHROME;
    kb->usbdelay = USB_DELAY_DEFAULT;

    // Perform OS-specific setup
    DELAY_LONG(kb);
    if(os_setupusb(kb))
        goto fail;
    // Make up a device name and serial if they weren't assigned
    if(!kb->serial[0])
        snprintf(kb->serial, SERIAL_LEN, "%04x:%04x-NoID", kb->vendor, kb->product);
    if(!kb->name[0])
        snprintf(kb->name, KB_NAME_LEN, "%s %s", vendor_str(kb->vendor), product_str(kb->product));

    // Set up an input device for key events
    if(os_inputopen(kb))
        goto fail;
    if(pthread_create(&kb->inputthread, 0, os_inputmain, kb))
        goto fail;
    pthread_detach(kb->inputthread);
    if(os_setupindicators(kb))
        goto fail;

    // Set up device
    vt->allocprofile(kb);
    vt->updateindicators(kb, 1);
    pthread_mutex_unlock(imutex(kb));
    if(vt->start(kb, 0) && usb_tryreset(kb))
        goto fail_noinput;

    // Make /dev path
    if(mkdevpath(kb))
        goto fail_noinput;

    // Finished. Enter main loop
    int index = INDEX_OF(kb, keyboard);
    ckb_info("Setup finished for %s%d\n", devpath, index);
    updateconnected();
    return devmain(kb);

    fail:
    pthread_mutex_unlock(imutex(kb));
    fail_noinput:
    closeusb(kb);
    pthread_mutex_unlock(dmutex(kb));
    return 0;
}
Beispiel #2
0
static void intreport(void* context, IOReturn result, void* sender, IOHIDReportType reporttype, uint32_t reportid, uint8_t* data, CFIndex length){
    usbdevice* kb = context;
    pthread_mutex_lock(imutex(kb));
    if(IS_MOUSE(kb->vendor, kb->product)){
        if(length == 10)
            hid_mouse_translate(kb->input.keys, &kb->input.rel_x, &kb->input.rel_y, -2, length, data);
    } else if(HAS_FEATURES(kb, FEAT_RGB)){
        switch(length){
        case 8:
            // RGB EP 1: 6KRO (BIOS mode) input
            hid_kb_translate(kb->input.keys, -1, length, data);
            break;
        case 21:
        case 5:
            // RGB EP 2: NKRO (non-BIOS) input. Accept only if keyboard is inactive
            if(!kb->active)
                hid_kb_translate(kb->input.keys, -2, length, data);
            break;
        case MSG_SIZE:
            // RGB EP 3: Corsair input
            memcpy(kb->input.keys, data, N_KEYBYTES_KB);
            break;
        }
    } else {
        switch(length){
        case 8:
            // Non-RGB EP 1: 6KRO input
            hid_kb_translate(kb->input.keys, 1, length, data);
            break;
        case 4:
            // Non-RGB EP 2: media keys
            hid_kb_translate(kb->input.keys, 2, length, data);
            break;
        case 15:
            // Non-RGB EP 3: NKRO input
            hid_kb_translate(kb->input.keys, 3, length, data);
            break;
        }
    }
    inputupdate(kb);
    pthread_mutex_unlock(imutex(kb));
}
Beispiel #3
0
// Vtable selector
static const devcmd* get_vtable(short vendor, short product){
    return IS_MOUSE(vendor, product) ? &vtable_mouse : IS_RGB(vendor, product) ? &vtable_keyboard : &vtable_keyboard_nonrgb;
}
Beispiel #4
0
void* os_inputmain(void* context){
    usbdevice* kb = context;
    int fd = kb->handle;
    short vendor = kb->vendor, product = kb->product;
    int index = INDEX_OF(kb, keyboard);
    ckb_info("Starting input thread for %s%d\n", devpath, index);

    // Monitor input transfers on all endpoints
    int urbcount = 3;
    struct usbdevfs_urb urbs[urbcount];
    memset(urbs, 0, sizeof(urbs));
    urbs[0].buffer_length = 8;
    if(IS_RGB(vendor, product)){
        if(IS_MOUSE(vendor, product))
            urbs[1].buffer_length = 10;
        else
            urbs[1].buffer_length = 21;
        urbs[2].buffer_length = MSG_SIZE;
        urbs[3].buffer_length = MSG_SIZE;
    } else {
        urbs[1].buffer_length = 4;
        urbs[2].buffer_length = 15;
    }
    // Submit URBs
    for(int i = 0; i < urbcount; i++){
        urbs[i].type = USBDEVFS_URB_TYPE_INTERRUPT;
        urbs[i].endpoint = 0x80 | (i + 1);
        urbs[i].buffer = malloc(urbs[i].buffer_length);
        ioctl(fd, USBDEVFS_SUBMITURB, urbs + i);
    }
    // Start monitoring input
    while(1){
        struct usbdevfs_urb* urb = 0;
        if(ioctl(fd, USBDEVFS_REAPURB, &urb)){
            if(errno == ENODEV || errno == ENOENT || errno == ESHUTDOWN)
                // Stop the thread if the handle closes
                break;
            else if(errno == EPIPE && urb){
                // On EPIPE, clear halt on the endpoint
                ioctl(fd, USBDEVFS_CLEAR_HALT, &urb->endpoint);
                // Re-submit the URB
                if(urb)
                    ioctl(fd, USBDEVFS_SUBMITURB, urb);
                urb = 0;
            }
        }
        if(urb){
            // Process input (if any)
            pthread_mutex_lock(imutex(kb));
            if(IS_MOUSE(vendor, product)){
                if(urb->endpoint == 0x82){
                    // RGB mouse input
                    hid_mouse_translate(kb->input.keys, &kb->input.rel_x, &kb->input.rel_y, -(urb->endpoint & 0xF), urb->actual_length, urb->buffer);
                }
            } else if(IS_RGB(vendor, product)){
                switch(urb->endpoint){
                case 0x81:
                    // RGB EP 1: 6KRO (BIOS mode) input
                    hid_kb_translate(kb->input.keys, -1, urb->actual_length, urb->buffer);
                    break;
                case 0x82:
                    // RGB EP 2: NKRO (non-BIOS) input. Accept only if keyboard is inactive
                    if(!kb->active)
                        hid_kb_translate(kb->input.keys, -2, urb->actual_length, urb->buffer);
                    break;
                case 0x83:
                    // RGB EP 3: Corsair input
                    memcpy(kb->input.keys, urb->buffer, N_KEYBYTES_KB);
                    break;
                }
            } else
                // Non-RGB input
                hid_kb_translate(kb->input.keys, urb->endpoint & 0xF, urb->actual_length, urb->buffer);
            inputupdate(kb);
            pthread_mutex_unlock(imutex(kb));
            // Re-submit the URB
            ioctl(fd, USBDEVFS_SUBMITURB, urb);
            urb = 0;
        }
    }
    // Clean up
    ckb_info("Stopping input thread for %s%d\n", devpath, index);
    for(int i = 0; i < urbcount; i++){
        ioctl(fd, USBDEVFS_DISCARDURB, urbs + i);
        free(urbs[i].buffer);
    }
    return 0;
}
Beispiel #5
0
void editor (char *filename, int startpos)
{
    int stop    = FALSE; // exit main loop?
    int fline   = 0;     // no. of first displayed line
    int cline   = 0;     // no. of line with cursor
    int shift   = 0;     // shift to the right
    int ccol    = 0;     // column of the cursor position in the file window

    int        k, i, ndisp, rc, reply;
    char       *p, buf[1024];

    if (editor_open_file (filename) < 0) return;
    cline = min1 (startpos, nl-1);
    fline = max1 (0, cline - video_vsize()/2);

    // enter the loop
    while (1)
    {
        if (stop)
        {
            rc = 0;
            if (changed)
            {
                rc = -1;
                reply = fly_ask (0, "   Save file `%s'?   ", " Yes \n No \n Cancel ", filename);
                if (reply == 1) rc = editor_save_file (filename);
                if (reply == 2) rc = 0;
                if (reply == 3) stop = FALSE;
            }
            if (rc == 0) break;
        }
        
        ndisp = video_vsize()-1;
        // draw the screen
        for (i=0; i<ndisp; i++)
        {
            video_put_n_cell (' ', _BackWhite+_Black, video_hsize(), i, 0);
            if (i+fline < nl)
                editor_display_line (i, fline+i, shift);
        }
        video_put_n_cell (' ', _BackBlue+_White, video_hsize(), video_vsize()-1, 0);
        snprintf1 (buf, sizeof(buf), "L%d:C%d:S%d %c %s%s", cline, ccol, shift, fl_sym.v,
                 changed ? "*" : "", filename);
        video_put (buf, video_vsize()-1, 0);
        video_set_cursor (cline-fline, ccol-shift);
        video_update (0);

        // get a keyboard/mouse event and process it
        k = getmessage (-1);
        if (IS_KEY(k))
        {
            switch (k)
            {
                // Navigation keys
                
            case _Up:
            case _Down:
            case _PgUp:
            case _PgDn:
                fly_scroll_it (k, &fline, &cline, nl, video_vsize()-1);
                break;

            case _Right:
                ccol++;
                if (ccol-shift > video_hsize()-1) shift = ccol-video_hsize()+1;
                break;

            case _Left:
                ccol = max1 (ccol-1, 0);
                if (ccol < shift) shift = ccol;
                break;

            case _Home:
                ccol = 0; shift = 0;
                break;

            case _End:
                ccol = strlen(lines[cline]);
                if (ccol-shift > video_hsize()-1) shift = ccol-video_hsize()+1;
                break;

            case _CtrlHome:
                fline = 0; cline = 0; ccol = 0; shift = 0; break;

            case _CtrlEnd:
                fline = max1 (0, nl-video_vsize()+1);
                cline = min1 (fline+video_vsize()-1, nl-1);
                shift = 0;
                ccol = 0;
                break;

                // Action keys

            case _CtrlY:
                put_clipboard (lines[cline]);
                free (lines[cline]);
                for (i=cline; i<nl-1; i++)
                    lines[i] = lines[i+1];
                nl--;
                changed = TRUE;
                break;

            case _ShiftInsert:
            case _CtrlV:
                p = get_clipboard ();
                if (p == NULL || *p == '\0') break;
                if (nl == na)
                {
                    na *= 2;
                    lines = realloc (lines, sizeof(char *) * na);
                }
                for (i=nl-1; i>cline; i--)
                    lines[i+1] = lines[i];
                lines[cline+1] = p;
                ccol = 0;
                shift = 0;
                cline++;
                if (cline-fline == video_vsize()-1) fline++;
                nl++;
                changed = TRUE;
                break;

            case _BackSpace:
                if (ccol == 0)
                {
                    // ccol == 0: glue this line to the previous
                    if (cline == 0) break;
                    p = malloc (strlen (lines[cline])+strlen(lines[cline-1])+1);
                    strcpy (p, lines[cline-1]);
                    strcat (p, lines[cline]);
                    ccol = strlen (lines[cline-1]);
                    if (ccol-shift > video_hsize()-1) shift = ccol-video_hsize()+1;
                    free (lines[cline-1]);
                    free (lines[cline]);
                    lines[cline-1] = p;
                    for (i=cline; i<nl-1; i++)
                        lines[i] = lines[i+1];
                    cline--;
                    nl--;
                }
                else
                {
                    // ccol != 0: delete char at ccol-1, move cursor left
                    str_delete (lines[cline], lines[cline]+ccol-1);
                    ccol--;
                    if (ccol < shift) shift = ccol;
                }
                changed = TRUE;
                break;

            case _Enter:
                if (nl == na)
                {
                    na *= 2;
                    lines = realloc (lines, sizeof(char *) * na);
                }
                for (i=nl-1; i>cline; i--)
                    lines[i+1] = lines[i];
                if (ccol < strlen (lines[cline]))
                {
                    lines[cline+1] = strdup (lines[cline]+ccol);
                    lines[cline][ccol] = '\0';
                }
                else
                {
                    lines[cline+1] = strdup ("");
                }
                ccol = 0;
                shift = 0;
                cline++;
                if (cline-fline == video_vsize()-1) fline++;
                nl++;
                changed = TRUE;
                break;

            case _Delete:
                if (ccol >= strlen (lines[cline]))
                {
                    // glue previous line to this one
                    if (cline == nl-1) break;
                    p = malloc (ccol+strlen(lines[cline+1])+1);
                    strcpy (p, lines[cline]);
                    memset (p+strlen(lines[cline]), ' ', ccol-strlen(lines[cline]));
                    strcpy (p+ccol, lines[cline+1]);
                    free (lines[cline]);
                    free (lines[cline+1]);
                    lines[cline] = p;
                    for (i=cline+1; i<nl-1; i++)
                        lines[i] = lines[i+1];
                    nl--;
                }
                else
                {
                    // ccol != 0: delete char at ccol-1, move cursor left
                    str_delete (lines[cline], lines[cline]+ccol);
                }
                changed = TRUE;
                break;

            case _F2:
                rc = editor_save_file (filename);
                if (rc == 0) changed = FALSE;
                break;
                
            case _Esc:
            case _F10:
                stop = TRUE; break;

                // character keys
                
            default:
                if (k >= ' ' && k <= 255)
                {
                    str_insert_at (cline, k, ccol);
                    ccol++;
                    changed = TRUE;
                }
            }
        }
        else if (IS_MOUSE(k))
        {
        }
        else if (IS_SYSTEM(k))
        {
            switch (SYS_TYPE(k))
            {
            case SYSTEM_QUIT:
                stop = TRUE; break;
            }
        }
    }

    if (nl != 0 && lines != NULL)
        for (i=0; i<nl; i++)
            free (lines[i]);
    if (na != 0 && lines != NULL) free (lines);
    na = 0;
    lines = NULL;
}