* Re: [BUG] KASAN: slab-use-after-free Read in irq_migrate_all_off_this_cpu
2026-08-30 18:48 ` Radu Rendec
@ 2026-09-09 17:56 ` Farhad Alemi
0 siblings, 0 replies; 7+ messages in thread
From: Farhad Alemi @ 2026-09-09 17:56 UTC (permalink / raw)
To: Radu Rendec; +Cc: Thomas Gleixner, Mark Brown, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1770 bytes --]
Hi Radu,
Please find attached the reproducer and the log; thanks!
On Sun, Aug 30, 2026 at 11:48 AM Radu Rendec <radu@rendec.net> wrote:
>
> On Sun, 2026-08-30 at 20:30 +0200, Thomas Gleixner wrote:
> > On Sat, Aug 29 2026 at 16:34, Radu Rendec wrote:
> > > On Thu, 2026-08-27 at 22:41 -0700, Farhad Alemi wrote:
> > > > BUG: KASAN: slab-out-of-bounds in
> > > > irq_migrate_all_off_this_cpu+0xdf/0xc80 kernel/irq/cpuhotplug.c:181
> > >
> > > Thanks for reporting this. For everyone interested, please note that it
> > > had been also reported by syzbot a few days before:
> > > https://lore.kernel.org/all/6a8c23a0.dbb3a75c.7844.0001.GAE@google.com/
> > > Currently there is no follow up to the syzbot report.
> >
> > The syzbot report is useless. It mumbles about memory allocated in the
> > networking stack which definitely can't end up in the interrupt
> > descriptor :)
>
> I know, and that's why I asked for the reproducer :)
>
> The stack trace of the UAF is valid though (and pretty much identical
> to the one in Farhad's report). I was just trying to point out that
> it's very likely the same bug.
>
> > > > Our reproducer.c is available upon request.
> >
> > See further down the thread :)
>
> Yes, I saw your and Mark's replies, and you're clearly many steps ahead :)
> In hindsight, I admit I was lazy and didn't bother to look further - partly
> because I thought it would be easier to investigate once I had the reproducer.
>
> If I could go back in time and start doing this kind of work 20 years
> ago (or even 10), I would. It certainly helps figure things out much
> faster when you've been doing this for a long time and also know how
> the code evolved over the years.
>
> --
> Best regards,
> Radu
[-- Attachment #2: 164_console.log --]
[-- Type: application/octet-stream, Size: 12631 bytes --]
Linux version 7.3.0-rc2-00006-g28924df2a08f (x@y) (Ubuntu clang version 21.1.8 (6ubuntu1), Ubuntu LLD 21.1.8) #1 SMP PREEMPT_DYNAMIC Mon Sep 7 16:56:53 MST 2026
[ 44.021699][ T9] usb 3-1: new high-speed USB device number 2 using dummy_hcd
[ 44.173291][ T9] usb 3-1: New USB device found, idVendor=0403, idProduct=c631, bcdDevice= 1.00
[ 44.179109][ T9] usb 3-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 44.200627][ T9] i2c-tiny-usb 3-1:1.0: version 1.00 found at bus 003 address 002
[ 44.208211][ T9] i2c i2c-2: connected i2c-tiny-usb device
[ 44.255216][ T9485] retu-mfd 2-0001: Retu v0.0 found
[ 44.263308][ T9485] genirq: Flags mismatch irq 0. 00002000 (RETU) vs. 00215a00 (timer)
[ 44.264283][ T9485] retu-mfd 2-0001: Failed to request IRQ 0 for RETU: -16
[ 44.265987][ T9485] retu-mfd 2-0001: probe with driver retu-mfd failed with error -16
[ 44.267048][ T9485] i2c i2c-2: new_device: Instantiated device retu at 0x01
[ 44.271471][ T9485] retu-mfd 2-0002: Tahvo v0.0 found
[ 44.275820][ T9485] genirq: Flags mismatch irq 0. 00002000 (TAHVO) vs. 00215a00 (timer)
[ 44.278060][ T9485] retu-mfd 2-0002: Failed to request IRQ 0 for TAHVO: -16
[ 44.282408][ T9485] retu-mfd 2-0002: probe with driver retu-mfd failed with error -16
[ 44.284261][ T9485] i2c i2c-2: new_device: Instantiated device tahvo at 0x02
[ 44.307505][ T23] numa_remove_cpu cpu 1 node 0: mask now 0
[ 44.307515][ T23] numa_remove_cpu cpu 1 node 1: mask now 0
[ 44.307972][ T23] ==================================================================
[ 44.307978][ T23] BUG: KASAN: slab-use-after-free in irq_migrate_all_off_this_cpu+0xdf/0xc50
[ 44.307998][ T23] Read of size 8 at addr ffff888021c431a8 by task migration/1/23
[ 44.308004][ T23]
[ 44.308014][ T23] CPU: 1 UID: 0 PID: 23 Comm: migration/1 Not tainted 7.3.0-rc2-00006-g28924df2a08f #1 PREEMPT(full)
[ 44.308022][ T23] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-debian-1.17.0-1ubuntu1 04/01/2014
[ 44.308027][ T23] Stopper: multi_cpu_stop+0x0/0x4a0 <- stop_cpus+0x130/0x1d0
[ 44.308048][ T23] Call Trace:
[ 44.308053][ T23] <TASK>
[ 44.308057][ T23] dump_stack_lvl+0xe8/0x150
[ 44.308066][ T23] print_address_description+0x55/0x1e0
[ 44.308074][ T23] ? irq_migrate_all_off_this_cpu+0xdf/0xc50
[ 44.308081][ T23] print_report+0x58/0x70
[ 44.308087][ T23] kasan_report+0x117/0x150
[ 44.308098][ T23] ? irq_migrate_all_off_this_cpu+0xdf/0xc50
[ 44.308105][ T23] irq_migrate_all_off_this_cpu+0xdf/0xc50
[ 44.308114][ T23] fixup_irqs+0x18/0x1e0
[ 44.308122][ T23] cpu_disable_common+0xb27/0xd90
[ 44.308131][ T23] native_cpu_disable+0x2f/0x40
[ 44.308138][ T23] take_cpu_down+0xca/0x330
[ 44.308147][ T23] ? __pfx_take_cpu_down+0x10/0x10
[ 44.308155][ T23] multi_cpu_stop+0x231/0x4a0
[ 44.308165][ T23] ? __pfx_multi_cpu_stop+0x10/0x10
[ 44.308175][ T23] cpu_stopper_thread+0x25e/0x3f0
[ 44.308185][ T23] smpboot_thread_fn+0x562/0xa60
[ 44.308194][ T23] ? smpboot_thread_fn+0x4d/0xa60
[ 44.308202][ T23] kthread+0x38b/0x480
[ 44.308210][ T23] ? __pfx_smpboot_thread_fn+0x10/0x10
[ 44.308217][ T23] ? __pfx_kthread+0x10/0x10
[ 44.308225][ T23] ret_from_fork+0x514/0xb70
[ 44.308233][ T23] ? __pfx_ret_from_fork+0x10/0x10
[ 44.308248][ T23] ? __switch_to+0xc79/0x1410
[ 44.308256][ T23] ? __pfx_kthread+0x10/0x10
[ 44.308263][ T23] ret_from_fork_asm+0x1a/0x30
[ 44.308273][ T23] </TASK>
[ 44.308276][ T23]
[ 44.308279][ T23] Allocated by task 9485:
[ 44.308283][ T23] kasan_save_track+0x3e/0x80
[ 44.308291][ T23] __kasan_kmalloc+0x93/0xb0
[ 44.308298][ T23] __kmalloc_cache_noprof+0x325/0x610
[ 44.308306][ T23] regmap_add_irq_chip_fwnode+0x380/0x2e90
[ 44.308320][ T23] regmap_add_irq_chip+0x6b/0x80
[ 44.308329][ T23] retu_probe+0x3ba/0x680
[ 44.308334][ T23] i2c_device_probe+0x894/0xc00
[ 44.308346][ T23] really_probe+0x267/0xaf0
[ 44.308353][ T23] __driver_probe_device+0x1e2/0x350
[ 44.308359][ T23] driver_probe_device+0x4f/0x240
[ 44.308365][ T23] __device_attach_driver+0x270/0x410
[ 44.308372][ T23] bus_for_each_drv+0x258/0x2f0
[ 44.308380][ T23] __device_attach+0x2c5/0x450
[ 44.308386][ T23] device_initial_probe+0xa1/0xd0
[ 44.308391][ T23] bus_probe_device+0x12a/0x220
[ 44.308399][ T23] device_add+0x7ec/0xb90
[ 44.308408][ T23] i2c_new_client_device+0xa1f/0x1160
[ 44.308417][ T23] new_device_store+0x24b/0x520
[ 44.308424][ T23] kernfs_fop_write_iter+0x3af/0x540
[ 44.308434][ T23] vfs_write+0x61d/0xb90
[ 44.308441][ T23] ksys_write+0x150/0x270
[ 44.308447][ T23] do_syscall_64+0x155/0x510
[ 44.308456][ T23] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 44.308463][ T23]
[ 44.308464][ T23] Freed by task 9485:
[ 44.308467][ T23] kasan_save_track+0x3e/0x80
[ 44.308474][ T23] kasan_save_free_info+0x46/0x50
[ 44.308481][ T23] __kasan_slab_free+0x5c/0x80
[ 44.308488][ T23] kfree+0x1c5/0x650
[ 44.308494][ T23] regmap_add_irq_chip_fwnode+0xd96/0x2e90
[ 44.308503][ T23] regmap_add_irq_chip+0x6b/0x80
[ 44.308512][ T23] retu_probe+0x3ba/0x680
[ 44.308517][ T23] i2c_device_probe+0x894/0xc00
[ 44.308525][ T23] really_probe+0x267/0xaf0
[ 44.308531][ T23] __driver_probe_device+0x1e2/0x350
[ 44.308537][ T23] driver_probe_device+0x4f/0x240
[ 44.308544][ T23] __device_attach_driver+0x270/0x410
[ 44.308550][ T23] bus_for_each_drv+0x258/0x2f0
[ 44.308557][ T23] __device_attach+0x2c5/0x450
[ 44.308563][ T23] device_initial_probe+0xa1/0xd0
[ 44.308569][ T23] bus_probe_device+0x12a/0x220
[ 44.308576][ T23] device_add+0x7ec/0xb90
[ 44.308585][ T23] i2c_new_client_device+0xa1f/0x1160
[ 44.308593][ T23] new_device_store+0x24b/0x520
[ 44.308600][ T23] kernfs_fop_write_iter+0x3af/0x540
[ 44.308609][ T23] vfs_write+0x61d/0xb90
[ 44.308615][ T23] ksys_write+0x150/0x270
[ 44.308621][ T23] do_syscall_64+0x155/0x510
[ 44.308629][ T23] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 44.308635][ T23]
[ 44.308636][ T23] The buggy address belongs to the object at ffff888021c43000
[ 44.308636][ T23] which belongs to the cache kmalloc-1k of size 1024
[ 44.308645][ T23] The buggy address is located 424 bytes inside of
[ 44.308645][ T23] freed 1024-byte region [ffff888021c43000, ffff888021c43400)
[ 44.308652][ T23]
[ 44.308654][ T23] The buggy address belongs to the physical page:
[ 44.308659][ T23] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x21c40
[ 44.308666][ T23] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[ 44.308672][ T23] flags: 0xfff00000000040(head|node=0|zone=1|lastcpupid=0x7ff)
[ 44.308682][ T23] page_type: f5(slab)
[ 44.308692][ T23] raw: 00fff00000000040 ffff88801b041dc0 dead000000000100 dead000000000122
[ 44.308698][ T23] raw: 0000000000000000 0000000000100010 00000000f5000000 0000000000000000
[ 44.308704][ T23] head: 00fff00000000040 ffff88801b041dc0 dead000000000100 dead000000000122
[ 44.308710][ T23] head: 0000000000000000 0000000000100010 00000000f5000000 0000000000000000
[ 44.308715][ T23] head: 00fff00000000003 fffffffffffffe01 00000000ffffffff 00000000ffffffff
[ 44.308721][ T23] head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000008
[ 44.308724][ T23] page dumped because: kasan: bad access detected
[ 44.308730][ T23] page_owner tracks the page as allocated
[ 44.308733][ T23] page last allocated via order 3, migratetype Unmovable, gfp_mask 0xd60c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_RETRY_MAYFAIL|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 1, tgid 1 (systemd), ts 8849800896
[ 44.308744][ T23] post_alloc_hook+0x1f9/0x250
[ 44.308751][ T23] get_page_from_freelist+0x235a/0x23e0
[ 44.308759][ T23] __alloc_frozen_pages_noprof+0x217/0x5a0
[ 44.308767][ T23] allocate_slab+0x7d/0x610
[ 44.308773][ T23] refill_objects+0x2d6/0x350
[ 44.308778][ T23] __pcs_replace_empty_main+0x2c9/0x6c0
[ 44.308787][ T23] __kvmalloc_node_noprof+0x64e/0x830
[ 44.308795][ T23] file_tty_write+0x2aa/0x9f0
[ 44.308803][ T23] do_iter_readv_writev+0x619/0x8c0
[ 44.308811][ T23] vfs_writev+0x33c/0x990
[ 44.308819][ T23] do_writev+0x154/0x2e0
[ 44.308826][ T23] do_syscall_64+0x155/0x510
[ 44.308835][ T23] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 44.308841][ T23] page last free pid 1 tgid 1 ts 8368557793 stack trace:
[ 44.308845][ T23] __free_frozen_pages+0xc9f/0xd90
[ 44.308852][ T23] __slab_free+0x274/0x2c0
[ 44.308859][ T23] qlist_free_all+0x99/0x100
[ 44.308866][ T23] kasan_quarantine_reduce+0x148/0x160
[ 44.308874][ T23] __kasan_slab_alloc+0x22/0x80
[ 44.308882][ T23] __kmalloc_noprof+0x30b/0x720
[ 44.308888][ T23] tomoyo_realpath_from_path+0xe3/0x5d0
[ 44.308899][ T23] tomoyo_path_number_perm+0x246/0x630
[ 44.308906][ T23] security_file_ioctl+0xc3/0x2a0
[ 44.308914][ T23] __se_sys_ioctl+0x47/0x170
[ 44.308921][ T23] do_syscall_64+0x155/0x510
[ 44.308929][ T23] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 44.308935][ T23]
[ 44.308937][ T23] Memory state around the buggy address:
[ 44.308941][ T23] ffff888021c43080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 44.308945][ T23] ffff888021c43100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 44.308950][ T23] >ffff888021c43180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 44.308953][ T23] ^
[ 44.308956][ T23] ffff888021c43200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 44.308961][ T23] ffff888021c43280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 44.308964][ T23] ==================================================================
[ 44.308973][ T23] Kernel panic - not syncing: KASAN: panic_on_warn set ...
[ 44.382675][ T23] CPU: 1 UID: 0 PID: 23 Comm: migration/1 Not tainted 7.3.0-rc2-00006-g28924df2a08f #1 PREEMPT(full)
[ 44.383651][ T23] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-debian-1.17.0-1ubuntu1 04/01/2014
[ 44.384605][ T23] Stopper: multi_cpu_stop+0x0/0x4a0 <- stop_cpus+0x130/0x1d0
[ 44.385282][ T23] Call Trace:
[ 44.385589][ T23] <TASK>
[ 44.385954][ T23] vpanic+0x56d/0xa60
[ 44.386351][ T23] ? __pfx_vpanic+0x10/0x10
[ 44.386792][ T23] panic+0xc5/0xd0
[ 44.387164][ T23] ? __pfx_panic+0x10/0x10
[ 44.387581][ T23] ? __pfx__printk+0x10/0x10
[ 44.388006][ T23] ? irq_migrate_all_off_this_cpu+0xdf/0xc50
[ 44.388554][ T23] ? irq_migrate_all_off_this_cpu+0xdf/0xc50
[ 44.389102][ T23] check_panic_on_warn+0x89/0xb0
[ 44.389565][ T23] ? irq_migrate_all_off_this_cpu+0xdf/0xc50
[ 44.390111][ T23] end_report+0x73/0x170
[ 44.390537][ T23] ? irq_migrate_all_off_this_cpu+0xdf/0xc50
[ 44.391113][ T23] kasan_report+0x128/0x150
[ 44.391566][ T23] ? irq_migrate_all_off_this_cpu+0xdf/0xc50
[ 44.392111][ T23] irq_migrate_all_off_this_cpu+0xdf/0xc50
[ 44.392645][ T23] fixup_irqs+0x18/0x1e0
[ 44.393039][ T23] cpu_disable_common+0xb27/0xd90
[ 44.393508][ T23] native_cpu_disable+0x2f/0x40
[ 44.393955][ T23] take_cpu_down+0xca/0x330
[ 44.394383][ T23] ? __pfx_take_cpu_down+0x10/0x10
[ 44.394852][ T23] multi_cpu_stop+0x231/0x4a0
[ 44.395293][ T23] ? __pfx_multi_cpu_stop+0x10/0x10
[ 44.395789][ T23] cpu_stopper_thread+0x25e/0x3f0
[ 44.396327][ T23] smpboot_thread_fn+0x562/0xa60
[ 44.396804][ T23] ? smpboot_thread_fn+0x4d/0xa60
[ 44.397290][ T23] kthread+0x38b/0x480
[ 44.397666][ T23] ? __pfx_smpboot_thread_fn+0x10/0x10
[ 44.398164][ T23] ? __pfx_kthread+0x10/0x10
[ 44.398595][ T23] ret_from_fork+0x514/0xb70
[ 44.399021][ T23] ? __pfx_ret_from_fork+0x10/0x10
[ 44.399490][ T23] ? __switch_to+0xc79/0x1410
[ 44.399923][ T23] ? __pfx_kthread+0x10/0x10
[ 44.400349][ T23] ret_from_fork_asm+0x1a/0x30
[ 44.400789][ T23] </TASK>
[ 45.465785][ T23] Shutting down cpus with NMI
[ 45.466540][ T23] Kernel Offset: disabled
[ 45.467086][ T23] Rebooting in 86400 seconds..
[-- Attachment #3: reproducer.c --]
[-- Type: application/octet-stream, Size: 5903 bytes --]
/*
* Reproducer for 164-kasan-slab-use-after-free-read-in-irq-migrate-all-off-this-cpu
*/
#define _GNU_SOURCE
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/usb/ch9.h>
#include <linux/usb/raw_gadget.h>
#define EP0_MAX 4096
/* i2c-tiny-usb command ids */
#define CMD_ECHO 0
#define CMD_GET_FUNC 1
#define CMD_SET_DELAY 2
#define CMD_GET_STATUS 3
#define CMD_I2C_IO 4
static int raw_gadget_fd = -1;
static const uint8_t device_descriptor[18] = {
18, USB_DT_DEVICE,
0x00, 0x02, /* bcdUSB 2.00 */
0x00, 0x00, 0x00, /* class/subclass/protocol */
64, /* bMaxPacketSize0 */
0x03, 0x04, /* idVendor 0x0403 */
0x31, 0xc6, /* idProduct 0xc631 (i2c-tiny-usb, FTDI ids) */
0x00, 0x01, /* bcdDevice */
0, 0, 0, /* iManufacturer/iProduct/iSerial */
1, /* bNumConfigurations */
};
static const uint8_t config_descriptor[18] = {
9, USB_DT_CONFIG,
18, 0, /* wTotalLength */
1, 1, 0, /* bNumInterfaces, bConfigurationValue, iConfiguration */
0xa0, 0x32, /* bmAttributes, bMaxPower */
9, USB_DT_INTERFACE,
0, 0, /* bInterfaceNumber, bAlternateSetting */
0, /* bNumEndpoints -- i2c-tiny-usb uses ep0 only */
0xff, 0x00, 0x00, /* vendor specific */
0, /* iInterface */
};
static void write_sysfs(const char *path, const char *value)
{
int fd = open(path, O_WRONLY);
if (fd < 0) {
printf("open %s: %s\n", path, strerror(errno));
return;
}
if (write(fd, value, strlen(value)) < 0)
printf("write %s <- %s: %s\n", path, value, strerror(errno));
close(fd);
}
/* An IN transfer with a data stage is completed with EP0_WRITE; everything
* else (including a zero-length IN) leaves ep0_out_pending set and must be
* acknowledged with EP0_READ. */
static void ep0_transfer(const void *data, uint32_t len)
{
uint8_t buf[sizeof(struct usb_raw_ep_io) + EP0_MAX];
struct usb_raw_ep_io *io = (void *)buf;
io->ep = 0;
io->flags = 0;
io->length = len > EP0_MAX ? EP0_MAX : len;
if (data)
memcpy(io->data, data, io->length);
ioctl(raw_gadget_fd, data ? USB_RAW_IOCTL_EP0_WRITE : USB_RAW_IOCTL_EP0_READ, io);
}
static void handle_control_request(const struct usb_ctrlrequest *ctrl)
{
uint8_t reply[EP0_MAX];
int len = -1;
memset(reply, 0, sizeof(reply));
if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR &&
(ctrl->wValue >> 8) == USB_DT_DEVICE) {
len = sizeof(device_descriptor);
memcpy(reply, device_descriptor, len);
} else if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR &&
(ctrl->wValue >> 8) == USB_DT_CONFIG) {
len = sizeof(config_descriptor);
memcpy(reply, config_descriptor, len);
} else if (ctrl->bRequest == USB_REQ_SET_CONFIGURATION) {
ioctl(raw_gadget_fd, USB_RAW_IOCTL_CONFIGURE, 0);
len = 0;
}
} else if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) {
switch (ctrl->bRequest) {
case CMD_GET_FUNC:
memset(reply, 0xff, 4); /* claim every I2C_FUNC_* bit */
len = 4;
break;
case CMD_GET_STATUS:
reply[0] = 1; /* STATUS_ADDRESS_ACK */
len = 1;
break;
case CMD_SET_DELAY:
len = ctrl->wLength;
break;
default:
/* CMD_I2C_IO with any BEGIN/END combination */
if ((ctrl->bRequest & ~3) == CMD_I2C_IO)
len = ctrl->wLength;
break;
}
}
if (len < 0) {
ioctl(raw_gadget_fd, USB_RAW_IOCTL_EP0_STALL, 0);
return;
}
if ((ctrl->bRequestType & USB_DIR_IN) && ctrl->wLength) {
if (len > (int)ctrl->wLength)
len = ctrl->wLength;
ep0_transfer(reply, (uint32_t)len);
} else {
ep0_transfer(NULL, ctrl->wLength);
}
}
static void *gadget_event_loop(void *unused)
{
uint8_t buf[sizeof(struct usb_raw_event) + EP0_MAX];
struct usb_raw_event *event = (void *)buf;
for (;;) {
event->type = 0;
event->length = EP0_MAX;
if (ioctl(raw_gadget_fd, USB_RAW_IOCTL_EVENT_FETCH, event) < 0) {
if (errno == EINTR)
continue;
return unused;
}
if (event->type == USB_RAW_EVENT_CONTROL)
handle_control_request((struct usb_ctrlrequest *)event->data);
}
return unused;
}
/* the i2c bus number whose adapter name is the emulated tiny-usb dongle */
static int find_tiny_usb_i2c_bus(void)
{
char path[64], name[128];
int bus, fd, n;
for (bus = 0; bus < 32; bus++) {
snprintf(path, sizeof(path),
"/sys/bus/i2c/devices/i2c-%d/name", bus);
fd = open(path, O_RDONLY);
if (fd < 0)
continue;
n = read(fd, name, sizeof(name) - 1);
close(fd);
if (n <= 0)
continue;
name[n] = 0;
if (strstr(name, "tiny-usb"))
return bus;
}
return -1;
}
int main(void)
{
struct usb_raw_init init = { .speed = USB_SPEED_HIGH };
char new_device_path[64];
pthread_t gadget_thread;
struct dirent *udc_ent;
char *udc_index;
DIR *udc_dir;
int bus = -1, i;
udc_dir = opendir("/sys/class/udc");
while ((udc_ent = readdir(udc_dir)) && udc_ent->d_name[0] == '.')
;
if (!udc_ent) {
printf("no UDC in /sys/class/udc\n");
return 1;
}
strcpy((char *)init.device_name, udc_ent->d_name);
strcpy((char *)init.driver_name, udc_ent->d_name);
closedir(udc_dir);
udc_index = strrchr((char *)init.driver_name, '.');
if (udc_index)
*udc_index = 0;
raw_gadget_fd = open("/dev/raw-gadget", O_RDWR);
ioctl(raw_gadget_fd, USB_RAW_IOCTL_INIT, &init);
ioctl(raw_gadget_fd, USB_RAW_IOCTL_RUN, 0);
pthread_create(&gadget_thread, NULL, gadget_event_loop, NULL);
for (i = 0; i < 300 && bus < 0; i++) {
usleep(50000);
bus = find_tiny_usb_i2c_bus();
}
if (bus < 0) {
printf("i2c-tiny-usb adapter never appeared\n");
return 1;
}
snprintf(new_device_path, sizeof(new_device_path),
"/sys/bus/i2c/devices/i2c-%d/new_device", bus);
write_sysfs(new_device_path, "retu 0x01\n");
write_sysfs(new_device_path, "tahvo 0x02\n");
write_sysfs("/sys/devices/system/cpu/cpu1/online", "0\n");
return 0;
}
^ permalink raw reply [flat|nested] 7+ messages in thread