Project

General

Profile

Revision 150

mouse files

View differences:

proj/Makefile
1 1
PROG=proj
2 2

  
3
SRCS= proj.c graphics.c kbc.c keyboard.c utils.c timer.c
3
SRCS= proj.c graphics.c kbc.c keyboard.c mouse.c utils.c timer.c
4 4

  
5 5
CPPFLAGS += -pedantic -D __LCOM_OPTIMIZED_
6 6

  
proj/mouse.c
1
#include <lcom/lcf.h>
2

  
3
#include "mouse.h"
4

  
5
#include "errors.h"
6
#include "kbc_macros.h"
7
#include "mouse_macros.h"
8
#include "kbc.h"
9

  
10
int (subscribe_mouse_interrupt)(uint8_t interrupt_bit, int *interrupt_id) {
11
    if (interrupt_id == NULL) return NULL_PTR;
12
    *interrupt_id = interrupt_bit;
13
    if (sys_irqsetpolicy(MOUSE_IRQ, IRQ_REENABLE | IRQ_EXCLUSIVE, interrupt_id)) return SBCR_ERROR;
14
    return SUCCESS;
15
}
16

  
17
int got_error_mouse_ih = 0;
18
int counter_mouse_ih = 0;
19

  
20
void (mouse_ih)(void) {
21
    uint8_t status = 0;
22
    got_error_mouse_ih = 0;
23
    if(counter_mouse_ih >= 3) counter_mouse_ih = 0;
24

  
25
    if ((got_error_mouse_ih = util_sys_inb(STATUS_REG, &status))) return;
26

  
27
    if (status & (TIME_OUT_REC | PARITY_ERROR)) {
28
        got_error_mouse_ih = OTHER_ERROR;
29
        return;
30
    }
31
    if (((status & AUX_MOUSE) == 0) || ((status & OUT_BUF_FUL) == 0)) {
32
        got_error_mouse_ih = READ_ERROR;
33
        return;
34
    }
35

  
36
    uint8_t byte = 0;
37

  
38
    if ((got_error_mouse_ih = util_sys_inb(OUTPUT_BUF, &byte))) return;
39

  
40
    /// This does not run if: I was expecting the first one but what I get is definitely not the first byte
41
    if((byte & FIRST_BYTE_ID)  || counter_mouse_ih){
42
        packet_mouse_ih[counter_mouse_ih++] = byte;
43
    }
44
}
45

  
46
struct packet (mouse_parse_packet)(const uint8_t *packet_bytes){
47
    struct packet pp;
48
    pp.bytes[0] = packet_bytes[0];
49
    pp.bytes[1] = packet_bytes[1];
50
    pp.bytes[2] = packet_bytes[2];
51
    pp.rb       = pp.bytes[0] & RIGHT_BUTTON;
52
    pp.mb       = pp.bytes[0] & MIDDLE_BUTTON;
53
    pp.lb       = pp.bytes[0] & LEFT_BUTTON;
54
    pp.delta_x  = sign_extend_byte((packet_bytes[0] & MSB_X_DELTA) != 0, pp.bytes[1]);
55
    pp.delta_y  = sign_extend_byte((packet_bytes[0] & MSB_Y_DELTA) != 0, pp.bytes[2]);
56
    pp.x_ov     = pp.bytes[0] & X_OVERFLOW;
57
    pp.y_ov     = pp.bytes[0] & Y_OVERFLOW;
58
    return pp;
59
}
60

  
61
int mouse_poll(struct packet *pp, uint16_t period){
62
    int ret = 0;
63

  
64
    uint8_t packet[3];
65
    uint8_t byte;
66
    if ((ret = mouse_issue_cmd(READ_DATA))) return ret;
67
    for(unsigned i = 0; i < 3; ++i){
68
        if((ret = mouse_poll_byte(&byte, period))) return ret;
69
        packet[i] = byte;
70
    }
71
    *pp = mouse_parse_packet(packet);
72
    return SUCCESS;
73
}
74

  
75
int (mouse_set_data_report)(int on){
76
    if(on) return mouse_issue_cmd(ENABLE_DATA_REP);
77
    else   return mouse_issue_cmd(   DIS_DATA_REP);
78
}
79

  
80
int (mouse_read_data)(uint8_t *data, uint16_t period) {
81
    int ret;
82
    if ((ret = mouse_issue_cmd(READ_DATA))) return ret;
83
    if ((ret = mouse_poll_byte(data, period))) return ret;
84
    return SUCCESS;
85
}
86

  
87
int (mouse_issue_cmd)(uint32_t cmd) {
88
    int ret;
89
    uint8_t ack = 0;
90
    for (unsigned int i = 0; i < KBC_NUM_TRIES; i++) {
91
        if ((ret = kbc_issue_cmd(MOUSE_WRITE_B))) return ret;
92
        if ((ret = kbc_issue_arg(cmd))) return ret;
93
        if ((ret = mouse_read_byte(&ack))) return ret;
94

  
95
        if (ack == ACK_OK) return SUCCESS;
96
        if (ack == ACK_ERROR) return INVALID_COMMAND;
97
        tickdelay(micros_to_ticks(DELAY));
98
    }
99
    return TIMEOUT_ERROR;
100
}
101

  
102
int (mouse_read_byte)(uint8_t *byte) {
103
    int ret = 0;
104
    uint8_t stat;
105
    for(int i = 0; i < KBC_NUM_TRIES; ++i){
106
        if((ret = util_sys_inb(STATUS_REG, &stat))) return ret;
107
        if((stat&OUT_BUF_FUL) && (stat&AUX_MOUSE)) {
108
            if(stat & (PARITY_ERROR | TIME_OUT_REC)) return OTHER_ERROR;
109
            if((ret = util_sys_inb(OUTPUT_BUF, byte))) return ret;
110
            else return SUCCESS;
111
        }
112
        tickdelay(micros_to_ticks(DELAY));
113
    }
114
    return TIMEOUT_ERROR;
115
}
116

  
117
int (mouse_poll_byte)(uint8_t *byte, uint16_t period) {
118
    int ret = 0;
119
    uint8_t stat;
120
    while(true){
121
        if((ret = util_sys_inb(STATUS_REG, &stat))) return ret;
122
        if((stat&OUT_BUF_FUL) && (stat&AUX_MOUSE)) {
123
            if(stat & (PARITY_ERROR | TIME_OUT_REC)) return OTHER_ERROR;
124
            if((ret = util_sys_inb(OUTPUT_BUF, byte))) return ret;
125
            else return SUCCESS;
126
        }
127
        tickdelay(micros_to_ticks(DELAY));
128
    }
129
}
130

  
131
int16_t (sign_extend_byte)(uint8_t sign_bit, uint8_t byte) {
132
    return (int16_t)(((0xFF * sign_bit)<<8) | byte);
133
}
0 134

  
proj/mouse.h
1
#ifndef MOUSE_H_INCLUDED
2
#define MOUSE_H_INCLUDED
3

  
4
#include <stdint.h>
5

  
6
/**
7
 * @brief Subscribes Mouse Interrupts and disables Minix Default IH
8
 * @param interrupt_bit Bit of Interrupt Vector that will be set when Mouse Interrupt is pending
9
 * @param interrupt_id Mouse Interrupt ID to specify the Mouse Interrupt in other calls
10
 * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
11
 * @see {_ERRORS_H_::errors}
12
 */
13
int (subscribe_mouse_interrupt)(uint8_t interrupt_bit, int *interrupt_id);
14

  
15
//These have to do with mouse_ih
16
int got_error_mouse_ih;
17
uint8_t packet_mouse_ih[3];
18
int counter_mouse_ih;
19

  
20
/**
21
 * @brief   Parse 3 bytes and returns it as a parsed, struct packet.
22
 * @param   packet_bytes    array of bytes to parse
23
 * @return  parsed struct packet
24
 */
25
struct packet (mouse_parse_packet)(const uint8_t *packet_bytes);
26

  
27
/**
28
 * @brief Polls mouse for data. Blocks execution until a valid mouse packet is obtained.
29
 * @param   pp      pointer to packet struct in which the result will be stored
30
 * @param   period  time (in milliseconds) the poller should wait between pollings of bytes
31
 * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
32
 */
33
int mouse_poll(struct packet *pp, uint16_t period);
34

  
35
/**
36
 * @brief Sets data report mode for mouse
37
 * @param   on  zero to disable data report, any other value to enable data report
38
 * @return  ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
39
 */
40
int (mouse_set_data_report)(int on);
41

  
42
/**
43
 * @brief Reads data byte from mouse
44
 * <summary>
45
 * Polls the mouse till data is available for reading
46
 * </summary>
47
 * @param data Pointer to variable where byte read from mouse will be stored
48
 * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
49
 * @see {_ERRORS_H_::errors}
50
 */
51
int (mouse_read_data)(uint8_t *data, uint16_t period);
52

  
53
/**
54
 * @brief Issues command to mouse
55
 * <summary>
56
 * Issues command to mouse, returns error after two consecutive errors reported by the acknowledgment byte
57
 * </summary>
58
 * @param cmd Command to be issued
59
 * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
60
 * @see {_ERRORS_H_::errors}
61
 */
62
int (mouse_issue_cmd)(uint32_t cmd);
63

  
64
/**
65
 * @brief Reads byte from mouse
66
 * <summary>
67
 * Reads byte from mouse, giving error if exceeds number of tries to read
68
 * </summary>
69
 * @param byte Pointer to variable where byte read from mouse will be stored
70
 * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
71
 * @see {_ERRORS_H_::errors}
72
 */
73
int (mouse_read_byte)(uint8_t *byte);
74

  
75
/**
76
 * @brief Polls OUT_BUF for byte coming from mouse.
77
 * @param   byte    pointer to byte read from OUT_BUF
78
 * @param   period  time (in milliseconds) the poller should wait between pollings of bytes
79
 * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
80
 */
81
int (mouse_poll_byte)(uint8_t *byte, uint16_t period);
82

  
83
/**
84
 * @brief Converts 9-bit number to 16-bit with sign extension
85
 * @param sign_bit  Sign bit identifiying the signal of the number
86
 * @param byte      Least significant byte that will be extended
87
 * @return Extended 9-bit number
88
 */
89
int16_t (sign_extend_byte)(uint8_t sign_bit, uint8_t byte);
90

  
91
#endif //MOUSE_H_INCLUDED
0 92

  
proj/mouse_macros.h
1
#ifndef MOUSE_MACROS_H_INCLUDED
2
#define MOUSE_MACROS_H_INCLUDED
3

  
4
/* Mouse Data Packet */
5
// Byte 0 - Button States
6
#define LEFT_BUTTON     BIT(0) /* @brief Left button click event*/
7
#define RIGHT_BUTTON    BIT(1) /* @brief Right button click event */
8
#define MIDDLE_BUTTON   BIT(2) /* @brief Middle button click event */
9
#define FIRST_BYTE_ID   BIT(3) /* @brief Identifier of first byte of packet CAREFUL: Not 100% accurate */
10
#define MSB_X_DELTA     BIT(4) /* @brief Most significant bit of X delta */
11
#define MSB_Y_DELTA     BIT(5) /* @brief Most significant bit of Y delta */
12
#define X_OVERFLOW      BIT(6) /* @brief X delta overflowed */
13
#define Y_OVERFLOW      BIT(7) /* @brief Y delta overflowed */
14
// Byte 1 - X delta
15
// Byte 2 - Y delta
16

  
17
/* Mouse Commands */
18
#define RESET           0xFF /* @brief Reset mouse */
19
#define RESEND          0xFE /* @brief Resend command */
20
#define DEFAULT         0xF6 /* @brief Set default values */
21
#define DIS_DATA_REP    0xF5 /* @brief Disable Data Reporting */
22
#define ENABLE_DATA_REP 0xF4 /* @brief Enable Data Reporting */
23
#define SET_SAMPLE_RT   0xF3 /* @brief Sets state sampling rate */
24
#define SET_REMOTE_MD   0xF0 /* @brief Sets Mouse on Remote Mode, data on request */
25
#define READ_DATA       0xEB /* @brief Sends data packet request */
26
#define SET_STREAM_MD   0xEA /* @brief Sets mouse on Stream Mode, data on events */
27
#define STATUS_REQUEST  0xE9 /* @brief Get mouse configuration */
28
#define SET_RESOLUTION  0xE8 /* @brief Sets resolution for mouse movement */
29
#define SCALING_ACC_MD  0xE7 /* @brief Sets scaling on acceleration mode */
30
#define SCALING_LIN_MD  0xE6 /* @brief Sets scaling on linear mode */
31

  
32
/* Mouse Controller Responses */
33
#define ACK_OK      0xFA /* @brief Operation sucessful */
34
#define ACK_INVALID 0xFE /* @brief Invalid Byte, first occurence */
35
#define ACK_ERROR   0xFC /* @brief Invalid Byte on resend */
36

  
37
#endif // MOUSE_MACROS_H_INCLUDED
0 38

  
proj/proj.c
8 8
#include "i8254.h"
9 9
#include "kbc_macros.h"
10 10
#include "graphics_macros.h"
11
#include "mouse_macros.h"
11 12
#include "proj_macros.h"
12 13
#include "errors.h"
13 14

  
......
15 16
#include "graphics.h"
16 17
#include "timer.h"
17 18
#include "keyboard.h"
19
#include "mouse.h"
18 20
#include "utils.h"
19 21

  
20 22
int main(int argc, char* argv[]) {
......
58 60
        return 1;
59 61
    }
60 62

  
63
    /// Mouse interrupt handling
64
    uint8_t mouse_irq_bit = MOUSE_IRQ;
65
    int mouse_id = 0;
66
    int mouse_irq = BIT(mouse_irq_bit);
67

  
68
    if (subscribe_mouse_interrupt(mouse_irq_bit, &mouse_id)) return 1; // subscribes mouse interrupts in exclusive mode
69
    if (sys_irqdisable(&mouse_id)) return 1; // temporarily disables our interrupts notifications
70
    if (mouse_set_data_report(true)) return 1; // enables mouse data reporting
71
    if (sys_irqenable(&mouse_id)) return 1; // re-enables our interrupts notifications
72

  
61 73
    /// cycle
62 74
    int good = 1;
63 75
    while (good) {
......
76 88
                    if (msg.m_notify.interrupts & timer_irq) { /* subscribed interrupt */
77 89
                        timer_int_handler();
78 90
                    }
91

  
92
                    if (msg.m_notify.interrupts & mouse_irq) { /* subscribed interrupt */
93
                        mouse_ih();
94
                    }
79 95
                    break;
80 96
                default:
81 97
                    break; /* no other notifications expected: do nothing */
......
95 111
        return 1;
96 112
    }
97 113

  
114
    // Unsubscribe Mouse Interrupts
115
    if (sys_irqdisable(&mouse_id)) return 1; // temporarily disables our interrupts notifications
116
    if (mouse_set_data_report(false)) return 1; // enables mouse data reporting
117
    if (sys_irqenable(&mouse_id)) return 1; // re-enables our interrupts notifications
118
    if (unsubscribe_interrupt(&mouse_id)) return 1; // unsubscribes interrupts
119

  
98 120
    return 0;
99 121
}

Also available in: Unified diff