Lines Matching +full:spi +full:- +full:crc
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2021-2023 Val Packett <val@packett.cool>
55 #include <dev/spibus/spi.h>
65 (((sc)->sc_gpe_bit == 0 && ((sc)->sc_irq_ih == NULL)) || cold ||\
75 ((sc)->sc_irq_ih != NULL ? SPI_FLAG_NO_SLEEP : 0)
96 return (&sc->sc_kb); in atopcase_get_child_by_device()
98 return (&sc->sc_tp); in atopcase_get_child_by_device()
118 err = SPIBUS_TRANSFER(device_get_parent(sc->sc_dev), sc->sc_dev, &cmd); in atopcase_receive_status()
121 device_printf(sc->sc_dev, "SPI error: %d\n", err); in atopcase_receive_status()
129 ATOPCASE_WAKEUP(sc, sc->sc_dev); in atopcase_receive_status()
131 device_printf(sc->sc_dev, "Failed to write command\n"); in atopcase_receive_status()
145 uint16_t pl_len, crc; in atopcase_process_message() local
148 pl_len = le16toh(hdr->len); in atopcase_process_message()
150 if (pl_len + sizeof(*hdr) + sizeof(crc) != msg_len) { in atopcase_process_message()
156 crc = le16toh(*(uint16_t *)((uint8_t *)payload + pl_len)); in atopcase_process_message()
157 if (crc != crc16(0, msg, msg_len - sizeof(crc))) { in atopcase_process_message()
168 (dst)[MIN(_len, sizeof(dst) - 1)] = '\0'; \ in atopcase_process_message()
172 && hdr->type == ATOPCASE_MSG_TYPE_REPORT(device)) { in atopcase_process_message()
173 if (ac->open) in atopcase_process_message()
174 ac->intr_handler(ac->intr_ctx, payload, pl_len); in atopcase_process_message()
176 && hdr->type == ATOPCASE_MSG_TYPE_INFO(ATOPCASE_INFO_IFACE) in atopcase_process_message()
177 && (ac = atopcase_get_child_by_device(sc, hdr->type_arg)) != NULL) { in atopcase_process_message()
179 CPOFF(ac->name, iface->name_len, iface->name_off); in atopcase_process_message()
180 DPRINTF("Interface #%d name: %s\n", ac->device, ac->name); in atopcase_process_message()
182 && hdr->type == ATOPCASE_MSG_TYPE_INFO(ATOPCASE_INFO_DESCRIPTOR) in atopcase_process_message()
183 && (ac = atopcase_get_child_by_device(sc, hdr->type_arg)) != NULL) { in atopcase_process_message()
184 memcpy(ac->rdesc, payload, pl_len); in atopcase_process_message()
185 ac->rdesc_len = ac->hw.rdescsize = pl_len; in atopcase_process_message()
186 DPRINTF("%s HID report descriptor: %*D\n", ac->name, in atopcase_process_message()
187 (int) ac->hw.rdescsize, ac->rdesc, " "); in atopcase_process_message()
189 && hdr->type == ATOPCASE_MSG_TYPE_INFO(ATOPCASE_INFO_DEVICE) in atopcase_process_message()
190 && hdr->type_arg == ATOPCASE_INFO_DEVICE) { in atopcase_process_message()
192 sc->sc_vid = le16toh(dev->vid); in atopcase_process_message()
193 sc->sc_pid = le16toh(dev->pid); in atopcase_process_message()
194 sc->sc_ver = le16toh(dev->ver); in atopcase_process_message()
195 CPOFF(sc->sc_vendor, dev->vendor_len, dev->vendor_off); in atopcase_process_message()
196 CPOFF(sc->sc_product, dev->product_len, dev->product_off); in atopcase_process_message()
197 CPOFF(sc->sc_serial, dev->serial_len, dev->serial_off); in atopcase_process_message()
199 device_printf(sc->sc_dev, "Device info descriptor:\n"); in atopcase_process_message()
200 printf(" Vendor: %s\n", sc->sc_vendor); in atopcase_process_message()
201 printf(" Product: %s\n", sc->sc_product); in atopcase_process_message()
202 printf(" Serial: %s\n", sc->sc_serial); in atopcase_process_message()
218 bzero(&sc->sc_junk, sizeof(struct atopcase_packet)); in atopcase_receive_packet()
219 cmd.tx_cmd = &sc->sc_junk; in atopcase_receive_packet()
224 err = SPIBUS_TRANSFER(device_get_parent(sc->sc_dev), sc->sc_dev, &cmd); in atopcase_receive_packet()
227 device_printf(sc->sc_dev, "SPI error: %d\n", err); in atopcase_receive_packet()
233 if (le16toh(pkt.checksum) != crc16(0, &pkt, sizeof(pkt) - 2)) { in atopcase_receive_packet()
270 sc->sc_booted = true; in atopcase_receive_packet()
275 /* handle multi-packet messages */ in atopcase_receive_packet()
277 if (offset != sc->sc_msg_len) { in atopcase_receive_packet()
280 offset, sc->sc_msg_len); in atopcase_receive_packet()
281 sc->sc_msg_len = 0; in atopcase_receive_packet()
285 if ((size_t)remaining + length + offset > sizeof(sc->sc_msg)) { in atopcase_receive_packet()
289 sc->sc_msg_len = 0; in atopcase_receive_packet()
293 memcpy(sc->sc_msg + offset, &pkt.data, length); in atopcase_receive_packet()
294 sc->sc_msg_len += length; in atopcase_receive_packet()
299 msg = sc->sc_msg; in atopcase_receive_packet()
300 msg_len = sc->sc_msg_len; in atopcase_receive_packet()
305 sc->sc_msg_len = 0; in atopcase_receive_packet()
324 cmd.rx_cmd = &sc->sc_junk; in atopcase_send()
332 if (sc->sc_irq_ih != NULL) in atopcase_send()
333 mtx_lock(&sc->sc_mtx); in atopcase_send()
335 sx_xlock(&sc->sc_sx); in atopcase_send()
337 sc->sc_wait_for_status = true; in atopcase_send()
338 err = SPIBUS_TRANSFER(device_get_parent(sc->sc_dev), sc->sc_dev, &cmd); in atopcase_send()
341 if (sc->sc_irq_ih != NULL) in atopcase_send()
342 mtx_unlock(&sc->sc_mtx); in atopcase_send()
344 sx_xunlock(&sc->sc_sx); in atopcase_send()
347 device_printf(sc->sc_dev, "SPI error: %d\n", err); in atopcase_send()
354 DPRINTFN(ATOPCASE_LLEVEL_DEBUG, "wait for: %p\n", sc->sc_dev); in atopcase_send()
355 err = tsleep(sc->sc_dev, 0, "atcstat", hz / 10); in atopcase_send()
357 sc->sc_wait_for_status = false; in atopcase_send()
367 --retries != 0) in atopcase_send()
388 struct atopcase_header *hdr = (struct atopcase_header *)pkt->data; in atopcase_create_message()
392 KASSERT(len <= ATOPCASE_DATA_SIZE - sizeof(struct atopcase_header), in atopcase_create_message()
396 pkt->direction = ATOPCASE_DIR_WRITE; in atopcase_create_message()
397 pkt->device = device; in atopcase_create_message()
398 pkt->length = htole16(sizeof(*hdr) + len + 2); in atopcase_create_message()
400 hdr->type = htole16(type); in atopcase_create_message()
401 hdr->type_arg = type_arg; in atopcase_create_message()
402 hdr->seq_no = seq_no++; in atopcase_create_message()
403 hdr->resp_len = htole16((resp_len == 0) ? len : resp_len); in atopcase_create_message()
404 hdr->len = htole16(len); in atopcase_create_message()
406 memcpy(pkt->data + sizeof(*hdr), payload, len); in atopcase_create_message()
407 msg_checksum = htole16(crc16(0, pkt->data, pkt->length - 2)); in atopcase_create_message()
408 memcpy(pkt->data + sizeof(*hdr) + len, &msg_checksum, 2); in atopcase_create_message()
409 pkt->checksum = htole16(crc16(0, (uint8_t*)pkt, sizeof(*pkt) - 2)); in atopcase_create_message()
418 &sc->sc_buf, ATOPCASE_DEV_INFO, type, device, NULL, 0, 0x200); in atopcase_request_desc()
419 return (atopcase_send(sc, &sc->sc_buf)); in atopcase_request_desc()
429 if (sc->sc_wait_for_status) { in atopcase_intr()
431 sc->sc_wait_for_status = false; in atopcase_intr()
445 ac->device = device; in atopcase_add_child()
448 strlcpy(ac->hw.name, "Apple MacBook", sizeof(ac->hw.name)); in atopcase_add_child()
449 ac->hw.idBus = BUS_SPI; in atopcase_add_child()
450 ac->hw.idVendor = sc->sc_vid; in atopcase_add_child()
451 ac->hw.idProduct = sc->sc_pid; in atopcase_add_child()
452 ac->hw.idVersion = sc->sc_ver; in atopcase_add_child()
453 strlcpy(ac->hw.idPnP, sc->sc_hid, sizeof(ac->hw.idPnP)); in atopcase_add_child()
454 strlcpy(ac->hw.serial, sc->sc_serial, sizeof(ac->hw.serial)); in atopcase_add_child()
456 * HID write and set_report methods executed on Apple SPI topcase in atopcase_add_child()
457 * hardware do the same request on SPI layer. Set HQ_NOWRITE quirk to in atopcase_add_child()
461 hid_add_dynamic_quirk(&ac->hw, HQ_NOWRITE); in atopcase_add_child()
467 device_printf(sc->sc_dev, "can't receive iface descriptor\n"); in atopcase_add_child()
471 DPRINTF("Get the \"%s\" HID report descriptor\n", ac->name); in atopcase_add_child()
475 device_printf(sc->sc_dev, "can't receive report descriptor\n"); in atopcase_add_child()
479 hidbus = device_add_child(sc->sc_dev, "hidbus", -1); in atopcase_add_child()
481 device_printf(sc->sc_dev, "can't add child\n"); in atopcase_add_child()
485 device_set_ivars(hidbus, &ac->hw); in atopcase_add_child()
486 ac->hidbus = hidbus; in atopcase_add_child()
498 if(!sc->sc_booted && tsleep(sc, 0, "atcboot", hz / 20) != 0) { in atopcase_init()
499 device_printf(sc->sc_dev, "can't establish communication\n"); in atopcase_init()
515 device_printf(sc->sc_dev, "can't receive device descriptor\n"); in atopcase_init()
519 err = atopcase_add_child(sc, &sc->sc_kb, ATOPCASE_DEV_KBRD); in atopcase_init()
522 err = atopcase_add_child(sc, &sc->sc_tp, ATOPCASE_DEV_TPAD); in atopcase_init()
527 sc->sc_backlight = backlight_register("atopcase", sc->sc_dev); in atopcase_init()
528 if (!sc->sc_backlight) { in atopcase_init()
529 device_printf(sc->sc_dev, "can't register backlight\n"); in atopcase_init()
533 if (sc->sc_tq != NULL) in atopcase_init()
534 taskqueue_enqueue_timeout(sc->sc_tq, &sc->sc_task, hz / 120); in atopcase_init()
536 bus_attach_children(sc->sc_dev); in atopcase_init()
548 err = device_delete_children(sc->sc_dev); in atopcase_destroy()
552 if (sc->sc_backlight) in atopcase_destroy()
553 backlight_destroy(sc->sc_backlight); in atopcase_destroy()
564 if (child == sc->sc_kb.hidbus) in atopcase_get_child_by_hidbus()
565 return (&sc->sc_kb); in atopcase_get_child_by_hidbus()
566 if (child == sc->sc_tp.hidbus) in atopcase_get_child_by_hidbus()
567 return (&sc->sc_tp); in atopcase_get_child_by_hidbus()
580 rdesc->rdsize = ATOPCASE_MSG_SIZE - sizeof(struct atopcase_header) - 2; in atopcase_intr_setup()
581 rdesc->grsize = 0; in atopcase_intr_setup()
582 rdesc->srsize = ATOPCASE_DATA_SIZE - sizeof(struct atopcase_header) - 2; in atopcase_intr_setup()
583 rdesc->wrsize = 0; in atopcase_intr_setup()
585 ac->intr_handler = intr; in atopcase_intr_setup()
586 ac->intr_ctx = context; in atopcase_intr_setup()
601 sx_xlock(&sc->sc_write_sx); in atopcase_intr_start()
602 else if (sc->sc_irq_ih != NULL) in atopcase_intr_start()
603 mtx_lock(&sc->sc_mtx); in atopcase_intr_start()
605 sx_xlock(&sc->sc_sx); in atopcase_intr_start()
606 ac->open = true; in atopcase_intr_start()
608 sx_xunlock(&sc->sc_write_sx); in atopcase_intr_start()
609 else if (sc->sc_irq_ih != NULL) in atopcase_intr_start()
610 mtx_unlock(&sc->sc_mtx); in atopcase_intr_start()
612 sx_xunlock(&sc->sc_sx); in atopcase_intr_start()
624 sx_xlock(&sc->sc_write_sx); in atopcase_intr_stop()
625 else if (sc->sc_irq_ih != NULL) in atopcase_intr_stop()
626 mtx_lock(&sc->sc_mtx); in atopcase_intr_stop()
628 sx_xlock(&sc->sc_sx); in atopcase_intr_stop()
629 ac->open = false; in atopcase_intr_stop()
631 sx_xunlock(&sc->sc_write_sx); in atopcase_intr_stop()
632 else if (sc->sc_irq_ih != NULL) in atopcase_intr_stop()
633 mtx_unlock(&sc->sc_mtx); in atopcase_intr_stop()
635 sx_xunlock(&sc->sc_sx); in atopcase_intr_stop()
653 if (ac->rdesc_len != len) in atopcase_get_rdesc()
655 memcpy(buf, ac->rdesc, len); in atopcase_get_rdesc()
668 if (len >= ATOPCASE_DATA_SIZE - sizeof(struct atopcase_header) - 2) in atopcase_set_report()
672 ac->name, id, len, len, buf, " "); in atopcase_set_report()
675 sx_xlock(&sc->sc_write_sx); in atopcase_set_report()
676 atopcase_create_message(&sc->sc_buf, ac->device, in atopcase_set_report()
677 ATOPCASE_MSG_TYPE_SET_REPORT(ac->device, id), 0, buf, len, 0); in atopcase_set_report()
678 err = atopcase_send(sc, &sc->sc_buf); in atopcase_set_report()
680 sx_xunlock(&sc->sc_write_sx); in atopcase_set_report()
694 * Hardware range is 32-255 for visible backlight, in atopcase_backlight_update_status()
697 payload.level = (props->brightness == 0) ? 0 : in atopcase_backlight_update_status()
698 (32 + (223 * props->brightness / 100)); in atopcase_backlight_update_status()
701 return (atopcase_set_report(dev, sc->sc_kb.hidbus, &payload, in atopcase_backlight_update_status()
710 props->brightness = sc->sc_backlight_level; in atopcase_backlight_get_status()
711 props->nlevels = 0; in atopcase_backlight_get_status()
719 info->type = BACKLIGHT_TYPE_KEYBOARD; in atopcase_backlight_get_info()
720 strlcpy(info->name, "Apple MacBook Keyboard", BACKLIGHTMAXNAMELENGTH); in atopcase_backlight_get_info()