Revision 150
mouse files
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